From f4c20290509d7ed3a8fd5304577e7a4cc0b9d974 Mon Sep 17 00:00:00 2001 From: Mike Buland Date: Tue, 3 Apr 2007 03:49:53 +0000 Subject: Ok, no code is left in src, it's all in src/old. We'll gradually move code back into src as it's fixed and re-org'd. This includes tests, which, I may write a unit test system into libbu++ just to make my life easier. --- src/arraylist.cpp | 100 ---- src/arraylist.h | 80 --- src/cgi.cpp | 644 -------------------- src/cgi.h | 196 ------- src/configmanagerbase.cpp | 63 -- src/configmanagerbase.h | 24 - src/confpair.cpp | 2 - src/confpair.h | 81 --- src/confpairbase.cpp | 17 - src/confpairbase.h | 24 - src/conftree.cpp | 9 - src/conftree.h | 19 - src/connection.cpp | 564 ------------------ src/connection.h | 411 ------------- src/connectionmanager.cpp | 397 ------------- src/connectionmanager.h | 169 ------ src/connectionmonitor.cpp | 10 - src/connectionmonitor.h | 47 -- src/exceptionbase.cpp | 70 --- src/exceptionbase.h | 105 ---- src/exceptions.cpp | 8 - src/exceptions.h | 25 - src/flexbuf.cpp | 229 -------- src/flexbuf.h | 162 ------ src/formula.cpp | 262 --------- src/formula.h | 77 --- src/fstring.cpp | 13 - src/fstring.h | 651 --------------------- src/hash.cpp | 113 ---- src/hash.h | 744 ------------------------ src/hashable.cpp | 1 - src/hashable.h | 12 - src/hashfunction.cpp | 10 - src/hashfunction.h | 48 -- src/hashfunctioncasestring.cpp | 39 -- src/hashfunctioncasestring.h | 28 - src/hashfunctionint.cpp | 20 - src/hashfunctionint.h | 26 - src/hashfunctionstring.cpp | 51 -- src/hashfunctionstring.h | 27 - src/hashtable.cpp | 424 -------------- src/hashtable.h | 308 ---------- src/http.cpp | 377 ------------ src/http.h | 273 --------- src/httpget.cpp | 263 --------- src/httpget.h | 44 -- src/linkedlist.cpp | 210 ------- src/linkedlist.h | 87 --- src/linkmessage.cpp | 44 -- src/linkmessage.h | 39 -- src/linkmessenger.cpp | 41 -- src/linkmessenger.h | 32 - src/list.cpp | 10 - src/list.h | 101 ---- src/md5.cpp | 190 ------ src/md5.h | 81 --- src/multilog.cpp | 102 ---- src/multilog.h | 130 ----- src/multilogchannel.cpp | 13 - src/multilogchannel.h | 46 -- src/multilogtext.cpp | 188 ------ src/multilogtext.h | 70 --- src/old/arraylist.cpp | 100 ++++ src/old/arraylist.h | 80 +++ src/old/cgi.cpp | 644 ++++++++++++++++++++ src/old/cgi.h | 196 +++++++ src/old/configmanagerbase.cpp | 63 ++ src/old/configmanagerbase.h | 24 + src/old/confpair.cpp | 2 + src/old/confpair.h | 81 +++ src/old/confpairbase.cpp | 17 + src/old/confpairbase.h | 24 + src/old/conftree.cpp | 9 + src/old/conftree.h | 19 + src/old/connection.cpp | 564 ++++++++++++++++++ src/old/connection.h | 411 +++++++++++++ src/old/connectionmanager.cpp | 397 +++++++++++++ src/old/connectionmanager.h | 169 ++++++ src/old/connectionmonitor.cpp | 10 + src/old/connectionmonitor.h | 47 ++ src/old/exceptionbase.cpp | 70 +++ src/old/exceptionbase.h | 105 ++++ src/old/exceptions.cpp | 8 + src/old/exceptions.h | 25 + src/old/flexbuf.cpp | 229 ++++++++ src/old/flexbuf.h | 162 ++++++ src/old/formula.cpp | 262 +++++++++ src/old/formula.h | 77 +++ src/old/fstring.cpp | 13 + src/old/fstring.h | 651 +++++++++++++++++++++ src/old/hash.cpp | 113 ++++ src/old/hash.h | 744 ++++++++++++++++++++++++ src/old/hashable.cpp | 1 + src/old/hashable.h | 12 + src/old/hashfunction.cpp | 10 + src/old/hashfunction.h | 48 ++ src/old/hashfunctioncasestring.cpp | 39 ++ src/old/hashfunctioncasestring.h | 28 + src/old/hashfunctionint.cpp | 20 + src/old/hashfunctionint.h | 26 + src/old/hashfunctionstring.cpp | 51 ++ src/old/hashfunctionstring.h | 27 + src/old/hashtable.cpp | 424 ++++++++++++++ src/old/hashtable.h | 308 ++++++++++ src/old/http.cpp | 377 ++++++++++++ src/old/http.h | 273 +++++++++ src/old/httpget.cpp | 263 +++++++++ src/old/httpget.h | 44 ++ src/old/linkedlist.cpp | 210 +++++++ src/old/linkedlist.h | 87 +++ src/old/linkmessage.cpp | 44 ++ src/old/linkmessage.h | 39 ++ src/old/linkmessenger.cpp | 41 ++ src/old/linkmessenger.h | 32 + src/old/list.cpp | 10 + src/old/list.h | 101 ++++ src/old/md5.cpp | 190 ++++++ src/old/md5.h | 81 +++ src/old/multilog.cpp | 102 ++++ src/old/multilog.h | 130 +++++ src/old/multilogchannel.cpp | 13 + src/old/multilogchannel.h | 46 ++ src/old/multilogtext.cpp | 188 ++++++ src/old/multilogtext.h | 70 +++ src/old/ordhash.cpp | 1 + src/old/ordhash.h | 104 ++++ src/old/paramproc.cpp | 514 ++++++++++++++++ src/old/paramproc.h | 153 +++++ src/old/plugger.cpp | 1 + src/old/plugger.h | 198 +++++++ src/old/pqueue.cpp | 33 ++ src/old/pqueue.h | 48 ++ src/old/programchain.cpp | 96 +++ src/old/programchain.h | 95 +++ src/old/programlink.cpp | 54 ++ src/old/programlink.h | 99 ++++ src/old/protocol.cpp | 20 + src/old/protocol.h | 62 ++ src/old/protocoltelnet.cpp | 316 ++++++++++ src/old/protocoltelnet.h | 77 +++ src/old/queue.cpp | 26 + src/old/queue.h | 45 ++ src/old/ringlist.cpp | 106 ++++ src/old/ringlist.h | 112 ++++ src/old/sbuffer.cpp | 67 +++ src/old/sbuffer.h | 40 ++ src/old/serializable.cpp | 8 + src/old/serializable.h | 34 ++ src/old/serializer.cpp | 338 +++++++++++ src/old/serializer.h | 80 +++ src/old/serializerbinary.cpp | 63 ++ src/old/serializerbinary.h | 24 + src/old/serializerbzip2.cpp | 88 +++ src/old/serializerbzip2.h | 27 + src/old/serializerconnection.cpp | 15 + src/old/serializerconnection.h | 24 + src/old/serializertext.cpp | 170 ++++++ src/old/serializertext.h | 49 ++ src/old/sfile.cpp | 74 +++ src/old/sfile.h | 29 + src/old/sha1.cpp | 161 +++++ src/old/sha1.h | 42 ++ src/old/singleton.h | 59 ++ src/old/sptr.cpp | 1 + src/old/sptr.h | 99 ++++ src/old/stack.cpp | 33 ++ src/old/stack.h | 50 ++ src/old/staticstring.cpp | 282 +++++++++ src/old/staticstring.h | 63 ++ src/old/stream.cpp | 10 + src/old/stream.h | 27 + src/old/stringrep.cpp | 19 + src/old/stringrep.h | 17 + src/old/tests/clistress.cpp | 20 + src/old/tests/confpair.cpp | 19 + src/old/tests/connect.cpp | 38 ++ src/old/tests/exception.cpp | 16 + src/old/tests/formula.cpp | 13 + src/old/tests/fstring.cpp | 48 ++ src/old/tests/hash.cpp | 116 ++++ src/old/tests/hashtest.cpp | 107 ++++ src/old/tests/hashtest2.cpp | 15 + src/old/tests/httpsrv/httpconnectionmonitor.cpp | 88 +++ src/old/tests/httpsrv/httpconnectionmonitor.h | 16 + src/old/tests/httpsrv/main.cpp | 22 + src/old/tests/log.cpp | 29 + src/old/tests/md5test.cpp | 19 + src/old/tests/ordhash.cpp | 48 ++ src/old/tests/param.cpp | 46 ++ src/old/tests/param.h | 21 + src/old/tests/plugin/main.cpp | 14 + src/old/tests/plugin/plugin.cpp | 10 + src/old/tests/plugin/plugin.h | 14 + src/old/tests/qsort.cpp | 228 ++++++++ src/old/tests/sbuffer.cpp | 27 + src/old/tests/serialize.cpp | 30 + src/old/tests/serializetext.cpp | 28 + src/old/tests/sha1.cpp | 44 ++ src/old/tests/sptr.cpp | 55 ++ src/old/tests/srvstress.cpp | 91 +++ src/old/tests/strhash.cpp | 12 + src/old/tests/teltest/main.cpp | 21 + src/old/tests/teltest/telnetmonitor.cpp | 54 ++ src/old/tests/teltest/telnetmonitor.h | 26 + src/old/tests/xmlreadtest.cpp | 29 + src/old/tests/xmlrepltest.cpp | 31 + src/old/tests/xmlwritetest.cpp | 48 ++ src/old/tokenstring.cpp | 163 ++++++ src/old/tokenstring.h | 114 ++++ src/old/tqsort.h | 207 +++++++ src/old/unit/hashtable/hashtable.cpp | 107 ++++ src/old/unit/xml/xml.cpp | 59 ++ src/old/xmldocument.cpp | 149 +++++ src/old/xmldocument.h | 171 ++++++ src/old/xmlfilereader.cpp | 58 ++ src/old/xmlfilereader.h | 47 ++ src/old/xmlfilewriter.cpp | 28 + src/old/xmlfilewriter.h | 45 ++ src/old/xmlnode.cpp | 445 ++++++++++++++ src/old/xmlnode.h | 236 ++++++++ src/old/xmlreader.cpp | 602 +++++++++++++++++++ src/old/xmlreader.h | 141 +++++ src/old/xmlstringreader.cpp | 38 ++ src/old/xmlstringreader.h | 49 ++ src/old/xmlstringwriter.cpp | 23 + src/old/xmlstringwriter.h | 50 ++ src/old/xmlwriter.cpp | 173 ++++++ src/old/xmlwriter.h | 96 +++ src/ordhash.cpp | 1 - src/ordhash.h | 104 ---- src/paramproc.cpp | 514 ---------------- src/paramproc.h | 153 ----- src/plugger.cpp | 1 - src/plugger.h | 198 ------- src/pqueue.cpp | 33 -- src/pqueue.h | 48 -- src/programchain.cpp | 96 --- src/programchain.h | 95 --- src/programlink.cpp | 54 -- src/programlink.h | 99 ---- src/protocol.cpp | 20 - src/protocol.h | 62 -- src/protocoltelnet.cpp | 316 ---------- src/protocoltelnet.h | 77 --- src/queue.cpp | 26 - src/queue.h | 45 -- src/ringlist.cpp | 106 ---- src/ringlist.h | 112 ---- src/sbuffer.cpp | 67 --- src/sbuffer.h | 40 -- src/serializable.cpp | 8 - src/serializable.h | 34 -- src/serializer.cpp | 338 ----------- src/serializer.h | 80 --- src/serializerbinary.cpp | 63 -- src/serializerbinary.h | 24 - src/serializerbzip2.cpp | 88 --- src/serializerbzip2.h | 27 - src/serializerconnection.cpp | 15 - src/serializerconnection.h | 24 - src/serializertext.cpp | 170 ------ src/serializertext.h | 49 -- src/sfile.cpp | 74 --- src/sfile.h | 29 - src/sha1.cpp | 161 ----- src/sha1.h | 42 -- src/singleton.h | 59 -- src/sptr.cpp | 1 - src/sptr.h | 99 ---- src/stack.cpp | 33 -- src/stack.h | 50 -- src/staticstring.cpp | 282 --------- src/staticstring.h | 63 -- src/stream.cpp | 10 - src/stream.h | 27 - src/stringrep.cpp | 19 - src/stringrep.h | 17 - src/tests/clistress.cpp | 20 - src/tests/confpair.cpp | 19 - src/tests/connect.cpp | 38 -- src/tests/exception.cpp | 16 - src/tests/formula.cpp | 13 - src/tests/fstring.cpp | 48 -- src/tests/hash.cpp | 116 ---- src/tests/hashtest.cpp | 107 ---- src/tests/hashtest2.cpp | 15 - src/tests/httpsrv/httpconnectionmonitor.cpp | 88 --- src/tests/httpsrv/httpconnectionmonitor.h | 16 - src/tests/httpsrv/main.cpp | 22 - src/tests/log.cpp | 29 - src/tests/md5test.cpp | 19 - src/tests/ordhash.cpp | 48 -- src/tests/param.cpp | 46 -- src/tests/param.h | 21 - src/tests/plugin/main.cpp | 14 - src/tests/plugin/plugin.cpp | 10 - src/tests/plugin/plugin.h | 14 - src/tests/qsort.cpp | 228 -------- src/tests/sbuffer.cpp | 27 - src/tests/serialize.cpp | 30 - src/tests/serializetext.cpp | 28 - src/tests/sha1.cpp | 44 -- src/tests/sptr.cpp | 55 -- src/tests/srvstress.cpp | 91 --- src/tests/strhash.cpp | 12 - src/tests/teltest/main.cpp | 21 - src/tests/teltest/telnetmonitor.cpp | 54 -- src/tests/teltest/telnetmonitor.h | 26 - src/tests/xmlreadtest.cpp | 29 - src/tests/xmlrepltest.cpp | 31 - src/tests/xmlwritetest.cpp | 48 -- src/tokenstring.cpp | 163 ------ src/tokenstring.h | 114 ---- src/tqsort.h | 207 ------- src/unit/hashtable/hashtable.cpp | 107 ---- src/unit/xml/xml.cpp | 59 -- src/xmldocument.cpp | 149 ----- src/xmldocument.h | 171 ------ src/xmlfilereader.cpp | 58 -- src/xmlfilereader.h | 47 -- src/xmlfilewriter.cpp | 28 - src/xmlfilewriter.h | 45 -- src/xmlnode.cpp | 445 -------------- src/xmlnode.h | 236 -------- src/xmlreader.cpp | 602 ------------------- src/xmlreader.h | 141 ----- src/xmlstringreader.cpp | 38 -- src/xmlstringreader.h | 49 -- src/xmlstringwriter.cpp | 23 - src/xmlstringwriter.h | 50 -- src/xmlwriter.cpp | 173 ------ src/xmlwriter.h | 96 --- 332 files changed, 17248 insertions(+), 17248 deletions(-) delete mode 100644 src/arraylist.cpp delete mode 100644 src/arraylist.h delete mode 100644 src/cgi.cpp delete mode 100644 src/cgi.h delete mode 100644 src/configmanagerbase.cpp delete mode 100644 src/configmanagerbase.h delete mode 100644 src/confpair.cpp delete mode 100644 src/confpair.h delete mode 100644 src/confpairbase.cpp delete mode 100644 src/confpairbase.h delete mode 100644 src/conftree.cpp delete mode 100644 src/conftree.h delete mode 100644 src/connection.cpp delete mode 100644 src/connection.h delete mode 100644 src/connectionmanager.cpp delete mode 100644 src/connectionmanager.h delete mode 100644 src/connectionmonitor.cpp delete mode 100644 src/connectionmonitor.h delete mode 100644 src/exceptionbase.cpp delete mode 100644 src/exceptionbase.h delete mode 100644 src/exceptions.cpp delete mode 100644 src/exceptions.h delete mode 100644 src/flexbuf.cpp delete mode 100644 src/flexbuf.h delete mode 100644 src/formula.cpp delete mode 100644 src/formula.h delete mode 100644 src/fstring.cpp delete mode 100644 src/fstring.h delete mode 100644 src/hash.cpp delete mode 100644 src/hash.h delete mode 100644 src/hashable.cpp delete mode 100644 src/hashable.h delete mode 100644 src/hashfunction.cpp delete mode 100644 src/hashfunction.h delete mode 100644 src/hashfunctioncasestring.cpp delete mode 100644 src/hashfunctioncasestring.h delete mode 100644 src/hashfunctionint.cpp delete mode 100644 src/hashfunctionint.h delete mode 100644 src/hashfunctionstring.cpp delete mode 100644 src/hashfunctionstring.h delete mode 100644 src/hashtable.cpp delete mode 100644 src/hashtable.h delete mode 100644 src/http.cpp delete mode 100644 src/http.h delete mode 100644 src/httpget.cpp delete mode 100644 src/httpget.h delete mode 100644 src/linkedlist.cpp delete mode 100644 src/linkedlist.h delete mode 100644 src/linkmessage.cpp delete mode 100644 src/linkmessage.h delete mode 100644 src/linkmessenger.cpp delete mode 100644 src/linkmessenger.h delete mode 100644 src/list.cpp delete mode 100644 src/list.h delete mode 100644 src/md5.cpp delete mode 100644 src/md5.h delete mode 100644 src/multilog.cpp delete mode 100644 src/multilog.h delete mode 100644 src/multilogchannel.cpp delete mode 100644 src/multilogchannel.h delete mode 100644 src/multilogtext.cpp delete mode 100644 src/multilogtext.h create mode 100644 src/old/arraylist.cpp create mode 100644 src/old/arraylist.h create mode 100644 src/old/cgi.cpp create mode 100644 src/old/cgi.h create mode 100644 src/old/configmanagerbase.cpp create mode 100644 src/old/configmanagerbase.h create mode 100644 src/old/confpair.cpp create mode 100644 src/old/confpair.h create mode 100644 src/old/confpairbase.cpp create mode 100644 src/old/confpairbase.h create mode 100644 src/old/conftree.cpp create mode 100644 src/old/conftree.h create mode 100644 src/old/connection.cpp create mode 100644 src/old/connection.h create mode 100644 src/old/connectionmanager.cpp create mode 100644 src/old/connectionmanager.h create mode 100644 src/old/connectionmonitor.cpp create mode 100644 src/old/connectionmonitor.h create mode 100644 src/old/exceptionbase.cpp create mode 100644 src/old/exceptionbase.h create mode 100644 src/old/exceptions.cpp create mode 100644 src/old/exceptions.h create mode 100644 src/old/flexbuf.cpp create mode 100644 src/old/flexbuf.h create mode 100644 src/old/formula.cpp create mode 100644 src/old/formula.h create mode 100644 src/old/fstring.cpp create mode 100644 src/old/fstring.h create mode 100644 src/old/hash.cpp create mode 100644 src/old/hash.h create mode 100644 src/old/hashable.cpp create mode 100644 src/old/hashable.h create mode 100644 src/old/hashfunction.cpp create mode 100644 src/old/hashfunction.h create mode 100644 src/old/hashfunctioncasestring.cpp create mode 100644 src/old/hashfunctioncasestring.h create mode 100644 src/old/hashfunctionint.cpp create mode 100644 src/old/hashfunctionint.h create mode 100644 src/old/hashfunctionstring.cpp create mode 100644 src/old/hashfunctionstring.h create mode 100644 src/old/hashtable.cpp create mode 100644 src/old/hashtable.h create mode 100644 src/old/http.cpp create mode 100644 src/old/http.h create mode 100644 src/old/httpget.cpp create mode 100644 src/old/httpget.h create mode 100644 src/old/linkedlist.cpp create mode 100644 src/old/linkedlist.h create mode 100644 src/old/linkmessage.cpp create mode 100644 src/old/linkmessage.h create mode 100644 src/old/linkmessenger.cpp create mode 100644 src/old/linkmessenger.h create mode 100644 src/old/list.cpp create mode 100644 src/old/list.h create mode 100644 src/old/md5.cpp create mode 100644 src/old/md5.h create mode 100644 src/old/multilog.cpp create mode 100644 src/old/multilog.h create mode 100644 src/old/multilogchannel.cpp create mode 100644 src/old/multilogchannel.h create mode 100644 src/old/multilogtext.cpp create mode 100644 src/old/multilogtext.h create mode 100644 src/old/ordhash.cpp create mode 100644 src/old/ordhash.h create mode 100644 src/old/paramproc.cpp create mode 100644 src/old/paramproc.h create mode 100644 src/old/plugger.cpp create mode 100644 src/old/plugger.h create mode 100644 src/old/pqueue.cpp create mode 100644 src/old/pqueue.h create mode 100644 src/old/programchain.cpp create mode 100644 src/old/programchain.h create mode 100644 src/old/programlink.cpp create mode 100644 src/old/programlink.h create mode 100644 src/old/protocol.cpp create mode 100644 src/old/protocol.h create mode 100644 src/old/protocoltelnet.cpp create mode 100644 src/old/protocoltelnet.h create mode 100644 src/old/queue.cpp create mode 100644 src/old/queue.h create mode 100644 src/old/ringlist.cpp create mode 100644 src/old/ringlist.h create mode 100644 src/old/sbuffer.cpp create mode 100644 src/old/sbuffer.h create mode 100644 src/old/serializable.cpp create mode 100644 src/old/serializable.h create mode 100644 src/old/serializer.cpp create mode 100644 src/old/serializer.h create mode 100644 src/old/serializerbinary.cpp create mode 100644 src/old/serializerbinary.h create mode 100644 src/old/serializerbzip2.cpp create mode 100644 src/old/serializerbzip2.h create mode 100644 src/old/serializerconnection.cpp create mode 100644 src/old/serializerconnection.h create mode 100644 src/old/serializertext.cpp create mode 100644 src/old/serializertext.h create mode 100644 src/old/sfile.cpp create mode 100644 src/old/sfile.h create mode 100644 src/old/sha1.cpp create mode 100644 src/old/sha1.h create mode 100644 src/old/singleton.h create mode 100644 src/old/sptr.cpp create mode 100644 src/old/sptr.h create mode 100644 src/old/stack.cpp create mode 100644 src/old/stack.h create mode 100644 src/old/staticstring.cpp create mode 100644 src/old/staticstring.h create mode 100644 src/old/stream.cpp create mode 100644 src/old/stream.h create mode 100644 src/old/stringrep.cpp create mode 100644 src/old/stringrep.h create mode 100644 src/old/tests/clistress.cpp create mode 100644 src/old/tests/confpair.cpp create mode 100644 src/old/tests/connect.cpp create mode 100644 src/old/tests/exception.cpp create mode 100644 src/old/tests/formula.cpp create mode 100644 src/old/tests/fstring.cpp create mode 100644 src/old/tests/hash.cpp create mode 100644 src/old/tests/hashtest.cpp create mode 100644 src/old/tests/hashtest2.cpp create mode 100644 src/old/tests/httpsrv/httpconnectionmonitor.cpp create mode 100644 src/old/tests/httpsrv/httpconnectionmonitor.h create mode 100644 src/old/tests/httpsrv/main.cpp create mode 100644 src/old/tests/log.cpp create mode 100644 src/old/tests/md5test.cpp create mode 100644 src/old/tests/ordhash.cpp create mode 100644 src/old/tests/param.cpp create mode 100644 src/old/tests/param.h create mode 100644 src/old/tests/plugin/main.cpp create mode 100644 src/old/tests/plugin/plugin.cpp create mode 100644 src/old/tests/plugin/plugin.h create mode 100644 src/old/tests/qsort.cpp create mode 100644 src/old/tests/sbuffer.cpp create mode 100644 src/old/tests/serialize.cpp create mode 100644 src/old/tests/serializetext.cpp create mode 100644 src/old/tests/sha1.cpp create mode 100644 src/old/tests/sptr.cpp create mode 100644 src/old/tests/srvstress.cpp create mode 100644 src/old/tests/strhash.cpp create mode 100644 src/old/tests/teltest/main.cpp create mode 100644 src/old/tests/teltest/telnetmonitor.cpp create mode 100644 src/old/tests/teltest/telnetmonitor.h create mode 100644 src/old/tests/xmlreadtest.cpp create mode 100644 src/old/tests/xmlrepltest.cpp create mode 100644 src/old/tests/xmlwritetest.cpp create mode 100644 src/old/tokenstring.cpp create mode 100644 src/old/tokenstring.h create mode 100644 src/old/tqsort.h create mode 100644 src/old/unit/hashtable/hashtable.cpp create mode 100644 src/old/unit/xml/xml.cpp create mode 100644 src/old/xmldocument.cpp create mode 100644 src/old/xmldocument.h create mode 100644 src/old/xmlfilereader.cpp create mode 100644 src/old/xmlfilereader.h create mode 100644 src/old/xmlfilewriter.cpp create mode 100644 src/old/xmlfilewriter.h create mode 100644 src/old/xmlnode.cpp create mode 100644 src/old/xmlnode.h create mode 100644 src/old/xmlreader.cpp create mode 100644 src/old/xmlreader.h create mode 100644 src/old/xmlstringreader.cpp create mode 100644 src/old/xmlstringreader.h create mode 100644 src/old/xmlstringwriter.cpp create mode 100644 src/old/xmlstringwriter.h create mode 100644 src/old/xmlwriter.cpp create mode 100644 src/old/xmlwriter.h delete mode 100644 src/ordhash.cpp delete mode 100644 src/ordhash.h delete mode 100644 src/paramproc.cpp delete mode 100644 src/paramproc.h delete mode 100644 src/plugger.cpp delete mode 100644 src/plugger.h delete mode 100644 src/pqueue.cpp delete mode 100644 src/pqueue.h delete mode 100644 src/programchain.cpp delete mode 100644 src/programchain.h delete mode 100644 src/programlink.cpp delete mode 100644 src/programlink.h delete mode 100644 src/protocol.cpp delete mode 100644 src/protocol.h delete mode 100644 src/protocoltelnet.cpp delete mode 100644 src/protocoltelnet.h delete mode 100644 src/queue.cpp delete mode 100644 src/queue.h delete mode 100644 src/ringlist.cpp delete mode 100644 src/ringlist.h delete mode 100644 src/sbuffer.cpp delete mode 100644 src/sbuffer.h delete mode 100644 src/serializable.cpp delete mode 100644 src/serializable.h delete mode 100644 src/serializer.cpp delete mode 100644 src/serializer.h delete mode 100644 src/serializerbinary.cpp delete mode 100644 src/serializerbinary.h delete mode 100644 src/serializerbzip2.cpp delete mode 100644 src/serializerbzip2.h delete mode 100644 src/serializerconnection.cpp delete mode 100644 src/serializerconnection.h delete mode 100644 src/serializertext.cpp delete mode 100644 src/serializertext.h delete mode 100644 src/sfile.cpp delete mode 100644 src/sfile.h delete mode 100644 src/sha1.cpp delete mode 100644 src/sha1.h delete mode 100644 src/singleton.h delete mode 100644 src/sptr.cpp delete mode 100644 src/sptr.h delete mode 100644 src/stack.cpp delete mode 100644 src/stack.h delete mode 100644 src/staticstring.cpp delete mode 100644 src/staticstring.h delete mode 100644 src/stream.cpp delete mode 100644 src/stream.h delete mode 100644 src/stringrep.cpp delete mode 100644 src/stringrep.h delete mode 100644 src/tests/clistress.cpp delete mode 100644 src/tests/confpair.cpp delete mode 100644 src/tests/connect.cpp delete mode 100644 src/tests/exception.cpp delete mode 100644 src/tests/formula.cpp delete mode 100644 src/tests/fstring.cpp delete mode 100644 src/tests/hash.cpp delete mode 100644 src/tests/hashtest.cpp delete mode 100644 src/tests/hashtest2.cpp delete mode 100644 src/tests/httpsrv/httpconnectionmonitor.cpp delete mode 100644 src/tests/httpsrv/httpconnectionmonitor.h delete mode 100644 src/tests/httpsrv/main.cpp delete mode 100644 src/tests/log.cpp delete mode 100644 src/tests/md5test.cpp delete mode 100644 src/tests/ordhash.cpp delete mode 100644 src/tests/param.cpp delete mode 100644 src/tests/param.h delete mode 100644 src/tests/plugin/main.cpp delete mode 100644 src/tests/plugin/plugin.cpp delete mode 100644 src/tests/plugin/plugin.h delete mode 100644 src/tests/qsort.cpp delete mode 100644 src/tests/sbuffer.cpp delete mode 100644 src/tests/serialize.cpp delete mode 100644 src/tests/serializetext.cpp delete mode 100644 src/tests/sha1.cpp delete mode 100644 src/tests/sptr.cpp delete mode 100644 src/tests/srvstress.cpp delete mode 100644 src/tests/strhash.cpp delete mode 100644 src/tests/teltest/main.cpp delete mode 100644 src/tests/teltest/telnetmonitor.cpp delete mode 100644 src/tests/teltest/telnetmonitor.h delete mode 100644 src/tests/xmlreadtest.cpp delete mode 100644 src/tests/xmlrepltest.cpp delete mode 100644 src/tests/xmlwritetest.cpp delete mode 100644 src/tokenstring.cpp delete mode 100644 src/tokenstring.h delete mode 100644 src/tqsort.h delete mode 100644 src/unit/hashtable/hashtable.cpp delete mode 100644 src/unit/xml/xml.cpp delete mode 100644 src/xmldocument.cpp delete mode 100644 src/xmldocument.h delete mode 100644 src/xmlfilereader.cpp delete mode 100644 src/xmlfilereader.h delete mode 100644 src/xmlfilewriter.cpp delete mode 100644 src/xmlfilewriter.h delete mode 100644 src/xmlnode.cpp delete mode 100644 src/xmlnode.h delete mode 100644 src/xmlreader.cpp delete mode 100644 src/xmlreader.h delete mode 100644 src/xmlstringreader.cpp delete mode 100644 src/xmlstringreader.h delete mode 100644 src/xmlstringwriter.cpp delete mode 100644 src/xmlstringwriter.h delete mode 100644 src/xmlwriter.cpp delete mode 100644 src/xmlwriter.h diff --git a/src/arraylist.cpp b/src/arraylist.cpp deleted file mode 100644 index ef21426..0000000 --- a/src/arraylist.cpp +++ /dev/null @@ -1,100 +0,0 @@ -#include "arraylist.h" -#include -#include - -ArrayList::ArrayList( int initSize, int growByFactor ) -{ - apData = new void *[initSize]; - nSize = 0; - nCapacity = initSize; - nGrowByFactor = growByFactor; -} - -ArrayList::~ArrayList( ) -{ - delete[] apData; -} - -void *ArrayList::getAt( int index ) -{ - if( index < 0 || index > nSize ) - return NULL; - - return apData[index]; -} - -void ArrayList::append( void *data ) -{ - insertBefore( data, nSize ); -} - -void ArrayList::insertBefore( void *data, int pos ) -{ - if( pos < 0 || pos > nSize ) - return; - - checkResize(); - memmove( &apData[pos+1], &apData[pos], (nSize-pos)*sizeof(void*) ); - apData[pos] = data; - nSize++; -} - -int ArrayList::getSize( ) -{ - return nSize; -} - -bool ArrayList::isEmpty( ) -{ - return nSize==0; -} - -void ArrayList::deleteAt( int index ) -{ - if( index < 0 || index >= nSize ) - return; - - memmove( &apData[index], &apData[index+1], (nSize-index-1)*sizeof(void *) ); - nSize--; -} - -void ArrayList::empty() -{ - // Probably the easiest as far as things go. - nSize = 0; -} - -void ArrayList::resizeTo( int newSize ) -{ - void **apNew = new void *[newSize]; - memmove( apNew, apData, nSize*sizeof(void *) ); - nCapacity = newSize; - delete[] apData; - apData = apNew; -} - -void ArrayList::checkResize() -{ - if( nSize >= nCapacity ) - { - resizeTo( nCapacity + nGrowByFactor ); - } -} - -void ArrayList::setSize( int newSize ) -{ - if( newSize < 0 ) - return; - - nSize = newSize; - checkResize(); -} - -void ArrayList::setAt( int index, void *data ) -{ - if( index < 0 || index >= nSize ) - return; - - apData[index] = data; -} - diff --git a/src/arraylist.h b/src/arraylist.h deleted file mode 100644 index 0fda34a..0000000 --- a/src/arraylist.h +++ /dev/null @@ -1,80 +0,0 @@ -/** \file arraylist.h - * Describes the ArrayList class. - *@author Mike Buland - */ -#ifndef ARRAY_LIST_H -#define ARRAY_LIST_H - -#include "list.h" - -/** A simple list which uses an array. This is a great choice if you won't do - * a lot of adding and deleting and need a fast random access list. Otherwise - * use the LinkedList. - *@author Mike Buland - */ -class ArrayList : public List -{ -public: - /** Creates an arraylist with some pre-defined specs spelled out. - *@param initSize the inital number of elements to allocate. - *@param growByFactor How much to increase the size of the array by - * each time we run out of room. - */ - ArrayList( int initSize=100, int growByFactor=10 ); - /** - * Destroy the ArrayList - */ - virtual ~ArrayList(); - - void *getAt( int nIndex ); - void append( void *pData ); - void insertBefore( void *pData, int nPos = 0 ); - int getSize( ); - bool isEmpty( ); - void deleteAt( int nIndex ); - void empty(); - void setSize( int nNewSize ); - void setAt( int nIndex, void *pData ); - -private: - /** - * Checks to see if the system needs to be resized, if it does, this will - * automatically resize based on your parameters. - */ - void checkResize(); - - /** - * Resize the system to a specified size. If it is larger, then all data - * will be retained, if smaller the elements at the end will be cut off. - *@param newSize The number of elements to include after resizing. - */ - void resizeTo( int newSize ); - - /** - * Actual master array of pointers. This is done to follow the List specs. - * All data transactions are performed with pointers or compatable - * primitive data-types. - */ - void **apData; - - /** - * The number of filled in elements in the array. This is the practical - * real size of the ArrayList for all userspace applications. - */ - int nSize; - - /** - * The number of elements allocated in memory. Not all of these have to be - * filled in, and it is usually larger than nSize so that adding and - * deleting elements is fast and easy. - */ - int nCapacity; - - /** - * The amount to grow by whenever the array needs resizing. - */ - int nGrowByFactor; -}; - -#endif - diff --git a/src/cgi.cpp b/src/cgi.cpp deleted file mode 100644 index 1fecbbe..0000000 --- a/src/cgi.cpp +++ /dev/null @@ -1,644 +0,0 @@ -#include -#include -#include -#include -#include - -#include "cgi.h" - -Cgi::Cgi( const char *strSource ) : - aContent( new HashFunctionString(), 151, true ) -{ - int length, j, k, mode = 0, slen = 0; - char hexbuf[3] = { 0, 0, 0 }; - char *buf, chr; - Item *cur = NULL; - int nCur = 0; - - if( strSource != NULL ) - { - loadContent( strSource ); - } - - if( ( getenv( "CONTENT_LENGTH" ) ) ) - { - if( !strcmp - ( getenv( "CONTENT_TYPE" ), - "application/x-www-form-urlencoded" ) ) - { - length = atoi( getenv( "CONTENT_LENGTH" ) ); - buf = new char[length + 1]; - fread( buf, 1, length, stdin ); - cur = new Item( ); - aVars.append( cur ); - cur->type = VAR_STDINPUT; - for( j = 0; j < length; j++ ) - { - switch ( buf[j] ) - { - case '=': - cur->name = new char[slen + 1]; - slen = 0; - break; - - case '&': - cur->value = new char[slen + 1]; - cur->len = slen; - slen = 0; - cur = new Item( ); - aVars.append( cur ); - cur->type = VAR_STDINPUT; - break; - - default: - switch ( buf[j] ) - { - case '%': /* per-cents mean a hex-code for an ASCII char */ - j += 2; - slen++; - break; - - default: /* Nothing special, move along, folks... */ - slen++; - break; - } - break; - } - } - cur->value = new char[slen + 1]; - cur->len = slen; - slen = 0; - mode = 0; - cur = ( Item * ) aVars.getAt( 0 ); - k = 0; - nCur = 0; - for( j = 0; j < length; j++ ) - { - switch ( buf[j] ) - { - case '=': - mode = 1; - k = 0; - break; - - case '&': - mode = 0; - k = 0; - nCur++; - cur = ( Item * ) aVars.getAt( nCur ); - break; - - default: - switch ( buf[j] ) - { - case '%': /* per-cents mean a hex-code for an ASCII char */ - hexbuf[0] = buf[++j]; - hexbuf[1] = buf[++j]; - chr = ( char ) ( strtol( hexbuf, NULL, 16 ) ); - break; - - case '+': /* Pluses mean spaces, odd, I know... */ - chr = ' '; - break; - - default: /* Nothing special, move along, folks... */ - chr = buf[j]; - break; - } - if( mode == 0 ) - { - cur->name[k] = chr; - cur->name[++k] = '\0'; - } - else - { - cur->value[k] = chr; - cur->value[++k] = '\0'; - } - break; - } - } - delete buf; - } - else if( !strncmp - ( getenv( "CONTENT_TYPE" ), "multipart/form-data;", 20 ) ) - { - char *boundary, *oname; - int blen, j, k, olen; - - length = atoi( getenv( "CONTENT_LENGTH" ) ); - buf = new char[length + 1]; - fread( buf, 1, length, stdin ); - for( blen = 0; buf[blen + 1] != '\n'; blen++ ); - boundary = new char[blen + 1]; - memcpy( boundary, buf, blen ); - boundary[blen] = '\0'; - j = blen + 2; - for( ;; ) - { - cur = new Item( ); - aVars.append( cur ); - cur->type = VAR_STDINPUT; - if( !strncmp - ( buf + j, "Content-Disposition: form-data; name=\"", - 38 ) ) - { - j += 38; - for( k = 0; buf[j + k] != '\"'; k++ ); - oname = cur->name = new char[k + 1]; - memcpy( cur->name, buf + j, k ); - olen = k; - cur->name[k] = '\0'; - j += k + 1; - if( !strncmp( buf + j, "; filename=\"", 12 ) ) /* Must be a file */ - { - /* Acquire file name */ - j += 12; - for( k = 0; buf[j + k] != '\"'; k++ ); - cur->value = new char[k + 1]; - memcpy( cur->value, buf + j, k ); - cur->value[k] = '\0'; - cur->len = k; - j += k + 3; - - /* Acquire content type */ - if( !strncmp( "Content-Type: ", buf + j, 14 ) ) - { - j += 14; - cur = new Item( ); - aVars.append( cur ); - cur->type = VAR_STDINPUT; - cur->name = new char[olen + 1]; - memcpy( cur->name, oname, olen + 1 ); - for( k = 0; buf[j + k + 1] != '\n'; k++ ); - cur->value = new char[k + 1]; - memcpy( cur->value, buf + j, k ); - cur->value[k] = '\0'; - cur->len = k; - j += k; - } - else - { - cur = new Item( ); - aVars.append( cur ); - cur->type = VAR_STDINPUT; - cur->name = new char[olen + 1]; - memcpy( cur->name, oname, olen + 1 ); - cur->value = new char[1]; - cur->value[0] = '\0'; - cur->len = 0; - } - j += 4; - - /* Acquire content */ - cur = new Item( ); - aVars.append( cur ); - cur->type = VAR_STDINPUT; - cur->name = new char[olen + 1]; - memcpy( cur->name, oname, olen + 1 ); - if( !strncmp( buf + j + k, boundary, blen ) ) - { - cur->value = new char[1]; - cur->value[0] = '\0'; - j += blen + 4; - } - else if( !strncmp( buf + j + k + 1, boundary, blen ) ) - { - cur->value = new char[1]; - cur->value[0] = '\0'; - j += blen + 5; - } - else - { - for( k = 0; - strncmp( buf + j + k + 2, boundary, blen ); - k++ ); - cur->value = new char[k + 1]; - memcpy( cur->value, buf + j, k ); - cur->value[k] = '\0'; - cur->len = k; - j += k + blen + 4; - } - } - else - { - j += 4; - for( k = 0; - strncmp( buf + j + k + 2, boundary, blen ); - k++ ); - cur->value = new char[k + 1]; - memcpy( cur->value, buf + j, k ); - cur->value[k] = '\0'; - cur->len = k; - j += k + blen + 4; - } - if( buf[j + 1] == '\n' ) - j += 2; - if( j >= length ) - break; - } - else - { - cur->name = ( char * ) "ERROR"; - cur->value = ( char * ) "Error here"; - } - } - } - delete buf; - } - - if( ( buf = getenv( "HTTP_COOKIE" ) ) ) - { - int lbase = aVars.getSize( ); - length = strlen( buf ); - cur = new Item( ); - aVars.append( cur ); - cur->type = VAR_COOKIE; - for( j = 0; j < length; j++ ) - { - switch ( buf[j] ) - { - case '=': - cur->name = new char[slen + 1]; - slen = 0; - break; - - case ';': - cur->value = new char[slen + 1]; - cur->len = slen; - slen = 0; - cur = new Item( ); - aVars.append( cur ); - cur->type = VAR_COOKIE; - break; - - default: - switch ( buf[j] ) - { - case '%': /* per-cents mean a hex-code for an ASCII char */ - j += 2; - slen++; - break; - - default: /* Nothing special, move along, folks... */ - slen++; - break; - } - break; - } - } - cur->value = new char[slen + 1]; - cur->len = slen; - slen = 0; - cur = ( Item * ) aVars.getAt( lbase ); - mode = 0; - k = 0; - nCur = lbase; - for( j = 0; j < length; j++ ) - { - switch ( buf[j] ) - { - case '=': - mode = 1; - k = 0; - break; - - case ';': - mode = 0; - k = 0; - nCur++; - cur = ( Item * ) aVars.getAt( nCur ); - break; - - default: - switch ( buf[j] ) - { - case '%': /* per-cents mean a hex-code for an ASCII char */ - hexbuf[0] = buf[++j]; - hexbuf[1] = buf[++j]; - chr = ( char ) ( strtol( hexbuf, NULL, 16 ) ); - break; - - case '+': /* Pluses mean spaces, odd, I know... */ - chr = ' '; - break; - - case ' ': - continue; - break; - - default: /* Nothing special, move along, folks... */ - chr = buf[j]; - break; - } - if( mode == 0 ) - { - cur->name[k] = chr; - cur->name[++k] = '\0'; - } - else - { - cur->value[k] = chr; - cur->value[++k] = '\0'; - } - break; - } - } - } - - if( ( buf = getenv( "QUERY_STRING" ) ) ) - { - if( strlen( buf ) > 0 ) - { - int lbase = aVars.getSize( ); - length = strlen( buf ); - cur = new Item( ); - aVars.append( cur ); - cur->type = VAR_CMDLINE; - for( j = 0; j < length; j++ ) - { - switch ( buf[j] ) - { - case '=': - cur->name = new char[slen + 1]; - slen = 0; - break; - - case '&': - cur->value = new char[slen + 1]; - cur->len = slen; - slen = 0; - cur = new Item( ); - aVars.append( cur ); - cur->type = VAR_CMDLINE; - break; - - default: - switch ( buf[j] ) - { - case '%': /* per-cents mean a hex-code for an ASCII char */ - j += 2; - slen++; - break; - - default: /* Nothing special, move along, folks... */ - slen++; - break; - } - break; - } - } - cur->value = new char[slen + 1]; - cur->len = slen; - slen = 0; - cur = ( Item * ) aVars.getAt( lbase ); - nCur = lbase; - mode = 0; - k = 0; - for( j = 0; j < length; j++ ) - { - switch ( buf[j] ) - { - case '=': - mode = 1; - k = 0; - break; - - case '&': - mode = 0; - k = 0; - nCur++; - cur = ( Item * ) aVars.getAt( nCur ); - break; - - default: - switch ( buf[j] ) - { - case '%': /* per-cents mean a hex-code for an ASCII char */ - hexbuf[0] = buf[++j]; - hexbuf[1] = buf[++j]; - chr = ( char ) ( strtol( hexbuf, NULL, 16 ) ); - break; - - case '+': /* Pluses mean spaces, odd, I know... */ - chr = ' '; - break; - - default: /* Nothing special, move along, folks... */ - chr = buf[j]; - break; - } - if( mode == 0 ) - { - cur->name[k] = chr; - cur->name[++k] = '\0'; - } - else - { - cur->value[k] = chr; - cur->value[++k] = '\0'; - } - break; - } - } - } - } -} - -Cgi::~Cgi( ) -{ -} - -char *Cgi::getVarValue( const char *name, int skip, unsigned char type ) -{ - for( int j = 0; j < aVars.getSize( ); j++ ) - { - Item *cur = ( Item * ) aVars.getAt( j ); - if( !strcmp( cur->name, name ) ) - { - if( ( cur->type & type ) ) - { - if( skip <= 0 ) - { - return cur->value; - } - else - { - skip--; - } - } - } - } - return NULL; -} - -int Cgi::getVarLength( const char *name, int skip, unsigned char type ) -{ - for( int j = 0; j < aVars.getSize( ); j++ ) - { - Item *cur = ( Item * ) aVars.getAt( j ); - if( !strcmp( cur->name, name ) ) - { - if( ( cur->type & type ) ) - { - if( skip <= 0 ) - { - return cur->len; - } - else - { - skip--; - } - } - } - } - return -1; -} - -void Cgi::writeDebugInfo() -{ - printf( "
\n" );
-    printf( "0x%02X - stdInput | 0x%02X - cookie | 0x%02X - cmdLine\n\n",
-             VAR_STDINPUT, VAR_COOKIE, VAR_CMDLINE );
-    for( int j = 0; j < aVars.getSize(  ); j++ )
-    {
-        Item *item = ( Item * ) aVars.getAt( j );
-        printf("[%s] = \"%s\" [0x%02X]\n", item->name,
-                 item->value, item->type );
-    }
-    printf( "
\n" ); -} - -void Cgi::writeContentHeader( int type ) -{ - switch( type ) - { - case headerHTML: - printf("Content-type: text/html\n\n"); - break; - } -} - -void Cgi::writeContent( const char *name, ...) -{ - char *templ = (char *)aContent.get(name); - - if( templ ) - { - va_list ap; - - va_start (ap, name); - vprintf (templ, ap); - va_end (ap); - } - else - { - printf("Error finding content labeled \"%s\"\n", name ); - } -} - -void Cgi::loadContent( const char *strSource ) -{ - FILE *fh = NULL; - if( strSource == NULL ) - { - extern char *program_invocation_short_name; - char *tmpName = new char[strlen(program_invocation_short_name)+10]; - memset( tmpName, 0, strlen(program_invocation_short_name)+10 ); - strcpy( tmpName, program_invocation_short_name ); - strcat( tmpName, ".content" ); - fh = fopen( tmpName, "rt" ); - delete tmpName; - } - else - { - fh = fopen( strSource, "rt" ); - } - - if( fh == NULL ) return; - - struct stat xStats; - - fstat( fileno( fh ), &xStats ); - - char *bigBuf = new char[xStats.st_size+1]; - memset( bigBuf, 0, xStats.st_size+1 ); - fread( bigBuf, 1, xStats.st_size, fh ); - fclose( fh ); - - // Now we can actually load stuff from the file, first we need to make us up a format... - int lSize=0; - struct Content - { - char *name; - char *value; - } xCont; - int j = 0; - while( j < xStats.st_size ) - { - // We're looking for a content-block init statement - for( ; j < xStats.st_size; j++ ) - { - if( bigBuf[j] == '#' ) - { - if( bigBuf[j+1] == '{' ) - { - break; - } - } - } - j=j+2; - if( j >= xStats.st_size ) break; - for( ; bigBuf[j] == ' ' || bigBuf[j] == '\t'; j++ ); - for( lSize = 0; lSize+j < xStats.st_size && bigBuf[lSize+j] != '\n' && bigBuf[lSize+j] != '\r'; lSize++ ); - xCont.name = new char[lSize+1]; - memset( xCont.name, 0, lSize+1 ); - memcpy( xCont.name, &bigBuf[j], lSize ); - j += lSize+1; - - for( lSize = 0; lSize+j < xStats.st_size; lSize++ ) - { - if( bigBuf[lSize+j] == '#' ) - { - if( bigBuf[lSize+j+1] == '}' ) - { - break; - } - } - } - xCont.value = new char[lSize+1]; - memset( xCont.value, 0, lSize+1 ); - memcpy( xCont.value, &bigBuf[j], lSize ); - - aContent.insert( xCont.name, xCont.value ); - - j += lSize + 2; - } -} - -void Cgi::writeCookie( char const *name, char const *value, char const *expires, char const *path, char const *domain, bool secure ) -{ - printf("Set-Cookie: %s=%s", name, value ); - - if( expires != NULL ) - { - printf("; expires=%s", expires ); - } - - if( path != NULL ) - { - printf("; path=%s", path ); - } - - if( domain != NULL ) - { - printf("; domain=%s", domain ); - } - - if( secure ) - { - printf("; secure"); - } - - printf("\n"); -} diff --git a/src/cgi.h b/src/cgi.h deleted file mode 100644 index 01142b5..0000000 --- a/src/cgi.h +++ /dev/null @@ -1,196 +0,0 @@ -/**\file cgi.h - * Describes extra params needed to use the Cgi class as well as the class - * itself. - *@author Mike Buland - */ - -#include "linkedlist.h" -#include "hashtable.h" -#include "hashfunctionstring.h" - -#define VAR_STDINPUT 0x01 /**< Variable came from stdinput, web form */ -#define VAR_COOKIE 0x02 /**< Variable came from a cookie */ -#define VAR_CMDLINE 0x04 /**< Variable came from commandline / uri */ -#define VAR_ANY 0xFF /**< Mask including all other types */ - -/** - * Cgi header processor originally designed for apache cgi programs. When used - * from apache with what I beleive are some sort of standard set of command - * line parameters and environment variables. This always worked for all of my - * purposes. This class will automatically extract all data from the system - * that you need and places it into tables and things for easy access. - * There are three types of input that data can come from, StandardInput, - * CommandLine, and Cookies. StandardInput is when you get formdata in - * multi-part forms, Cookies should usually be cookies that you set, and - * command line is everything after the question mark in the URL. - * This also contains some simple helpers for putting templated data into the - * HTTP data feed. - *@author Mike Buland - */ -class Cgi -{ -public: - /** - * Create a complete CGI object, this object will automatically read data - * from all available sources and be ready for use on the very next line! - * If strSource is filled in it will also automatically read in a content - * file, which is a simple file format containing named blocks of reusable - * templates. - *@param strSource Set to a filename in order to load up a content file. - */ - Cgi( const char *strSource = NULL ); - - /** - * Destroy the cgi object. - */ - virtual ~Cgi( ); - - /** - * Get's the value for a variable as a character string. The name is the - * name that was given on the URL or in the form or cookie. Skip can be - * set to any value above zero to retreive subsequent variables with the - * same name. The most obvious use of this is when dealing with file - * uploads, each file upload sends you three variables with the same name - * and different content. Finally the variable type determines where you - * will accept this variable from. This is generally a bit of a security - * thing, if you store login info in a cookie and don't want people getting - * in by faking the appropriate URL. - *@param name The name of the variable you wish to retreive. - *@param skip THe number of variables with the given name to skip before - * returning something meaningful. The only way to determine how many - * variables with the same name there are is to skip until you get a NULL - * value returned. - *@param type Can be set to any combination of VAR_STDINPUT, VAR_COOKIE, - * VAR_CMDLINE, or just VAR_ANY. This takes bitflags, so you can or the - * values together. If a variable is found but came from the wrong source - * it won't match any other criteria and will be treated as though it - * doesn't exist. - *@returns A null-terminated string representing the value of the requested - * variable, or NULL if the variable did not exist. If a variable does - * exist but has no value the string returned will start with a NULL char, - * but be a valid string. - */ - char *getVarValue( const char *name, int skip=0, unsigned char type=VAR_ANY ); - - /** - * This functions identically in every way to getVarValue, except that - * instead of returning a pointer to the variable's value, it returns the - * length of the variable's value string. The params are the same and so - * a call to both functions with the same params should yeild a value and - * a corresponding length. - *@param name The name of the variable you wish to retreive. - *@param skip THe number of variables with the given name to skip before - * returning something meaningful. The only way to determine how many - * variables with the same name there are is to skip until you get a NULL - * value returned. - *@param type Can be set to any combination of VAR_STDINPUT, VAR_COOKIE, - * VAR_CMDLINE, or just VAR_ANY. This takes bitflags, so you can or the - * values together. If a variable is found but came from the wrong source - * it won't match any other criteria and will be treated as though it - * doesn't exist. - *@returns The length of the value-string of the requested variable. If - * the requested variable is not found, -1 is returned. - */ - int getVarLength( const char *name, int skip=0, unsigned char type=VAR_ANY ); - - /** - * A handy little function that writes a load of debug info related to - * parsing CGI params to the standard output in html. This is generally - * best used at the end of a page. - */ - void writeDebugInfo(); - - /** - * Write a content header to the standard output. This should also be the - * first thing that you do (except for writing cookies) after initializing - * the Cgi class. You can select a type of header or content from the - * header enum, and a properly formatted header will show up on the - * standard output. - *@param type Any value from the header enum in this class. The default is - * to write an html header, probably the most common as well. - */ - void writeContentHeader( int type=headerHTML ); - - /** - * Write content to the stnadard output. The content variable should have - * been loaded during construction of the Cgi object or with the - * loadContent function. The content variable should be formatted just like - * a printf string, so that anything you want to put into it will have a % - * symbol replacement code, like %s, %d, etc. Since this actually uses a - * type of printf function everything from those docs work here. - *@param name The name of the content variable to format and write to - * stnadard output. - *@param ... As many params as you want to include, ala printf. - */ - void writeContent( const char *name, ...); - - /** - * Load a content file. I don't want to describe the format here, you can - * just read the code or find an example for now. Sorry. - *@param strSource The name of the file to open and read in to get the - * content loaded. - */ - void loadContent( const char *strSource = NULL ); - - /** - * Write a cookie-set header to the output stream. This should be done - * before any other content-headers are written. The specifics of this - * function are very simple, since I rely on the user's understanding of - * how standard HTTP/1.1 or HTTP/1.0 cookie syntax works. If you don't - * care then just use the name and value and the defaults should keep you - * in good stead for a long time. - *@param name The name of the cookie variable to set. - *@param value The value to set to that variable. - *@param expires The formatted string value for the date and time this - * cookie should expire. A NULL here will put a "until the browser closes" - * tag in. - *@param path The path (URL) that this cookie belongs to. If you run a lot - * of hosted servers or sub-sites that may have some shared URL bits then - * you may want to set this. The cookie should only be sent to URL's that - * match this as their first part. - *@param domain The domain that is allowed to read this, if not set, it's - * the domain the web browser contacted when they got the cookie. - *@param secure I'm not sure, I think it's something to tell if the cookie - * is safe to keep because any potentially valuable data is encypted or - * otherwise unusable. I could be wrong. - */ - void writeCookie( char const *name, char const *value, char const *expires=NULL, char const *path=NULL, char const *domain=NULL, bool secure=false ); - - /** - * A simple helper class to contain variable data. - */ - class Item - { - public: - /** - * Build an empty Item. - */ - Item( ) - { - name = NULL; - value = NULL; - len = 0; - type = 0; - } - /** The name of the item. */ - char *name; - /** The value of the item. */ - char *value; - /** The length of the item's value. */ - unsigned long len; - /** The type of the item (where it came from). */ - unsigned char type; - }; - - /** Header values */ - enum - { - headerHTML - }; - -private: - /** Keeps track of all contained variables. */ - LinkedList aVars; - /** Keeps track of all content variables. */ - HashTable aContent; -}; diff --git a/src/configmanagerbase.cpp b/src/configmanagerbase.cpp deleted file mode 100644 index ac55fe0..0000000 --- a/src/configmanagerbase.cpp +++ /dev/null @@ -1,63 +0,0 @@ -#include -#include -#include "xmlnode.h" -#include "xmlfilereader.h" -#include "configmanagerbase.h" - -ConfigManagerBase::ConfigManagerBase() -{ -} - -ConfigManagerBase::~ConfigManagerBase() -{ -} - -void ConfigManagerBase::addSearchPath( const std::string &sPath ) -{ - lSearchPath.push_back( sPath ); -} - -void ConfigManagerBase::loadConfig( const std::string &sFileName, const char *lpProfile ) -{ - // Try a few locations... - std::list::const_iterator i; - for( i = lSearchPath.begin(); i != lSearchPath.end(); i++ ) - { - if( parseConfig( (*i + sFileName).c_str(), lpProfile ) ) - { - break; - } - } -} - -bool ConfigManagerBase::parseConfig( const char *lpFileName, const char *lpProfile ) -{ - XmlNode *pRoot, *pCur; - XmlFileReader doc( lpFileName ); - - pRoot = doc.getRoot(); - if( pRoot == NULL ) - { - return false; - } - - if( strcmp("config", pRoot->getName() ) ) - { - return false; - } - - for( int j = 0;; j++ ) - { - pCur = pRoot->getChild( "profile", j ); - if( pCur == NULL ) - return false; - - if( !strcmp( pCur->getProperty("id"), lpProfile ) ) - { - return processProfile( pCur ); - } - } - - return false; -} - diff --git a/src/configmanagerbase.h b/src/configmanagerbase.h deleted file mode 100644 index 381cc1f..0000000 --- a/src/configmanagerbase.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef CONFIG_MANAGER_BASE_H -#define CONFIG_MANAGER_BASE_H - -#include -#include - -class ConfigManagerBase -{ -public: - ConfigManagerBase(); - virtual ~ConfigManagerBase(); - -public: - void addSearchPath( const std::string &sPath ); - void loadConfig( const std::string &sFileName, const char *lpProfile="default" ); - -private: - bool parseConfig( const char *lpFileName, const char *lpProfile ); - virtual bool processProfile( class XmlNode *pBase )=0; - - std::list lSearchPath; -}; - -#endif diff --git a/src/confpair.cpp b/src/confpair.cpp deleted file mode 100644 index 4741401..0000000 --- a/src/confpair.cpp +++ /dev/null @@ -1,2 +0,0 @@ -#include "confpair.h" - diff --git a/src/confpair.h b/src/confpair.h deleted file mode 100644 index 56eb06e..0000000 --- a/src/confpair.h +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef CONF_PAIR_H -#define CONF_PAIR_H - -#include -#include -#include -#include "confpairbase.h" - -/** - * - */ -template -class ConfPair : public ConfPairBase -{ -public: - ConfPair( const std::string &sName ) : - sName( sName ) - { } - - virtual ~ConfPair() - { } - - T &value() - { - return tValue; - } - - const std::string &name() - { - return sName; - } - - virtual void setFromString( const std::string &sStr ) - { - std::stringstream(sStr) >> tValue; - } - - virtual std::string getAsString() - { - std::stringstream tmp; - tmp << tValue; - return tmp.str(); - } - -private: - std::string sName; - T tValue; -}; - -template<> -void ConfPair::setFromString( const std::string &sStr ) -{ - tValue = sStr; -} - -template<> -std::string ConfPair::getAsString() -{ - return tValue; -} - -template<> -void ConfPair::setFromString( const std::string &sStr ) -{ - if( !strcasecmp( sStr.c_str(), "true" ) || - !strcasecmp( sStr.c_str(), "yes" ) || - !strcasecmp( sStr.c_str(), "on" ) ) - tValue = true; - else - tValue = false; -} - -template<> -std::string ConfPair::getAsString() -{ - if( tValue == true ) - return "True"; - return "False"; -} - -#endif diff --git a/src/confpairbase.cpp b/src/confpairbase.cpp deleted file mode 100644 index 1203dc0..0000000 --- a/src/confpairbase.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "confpairbase.h" - -ConfPairBase::ConfPairBase() -{ -} - -ConfPairBase::~ConfPairBase() -{ -} - -ConfPairBase &ConfPairBase::operator=( const std::string &s ) -{ - setFromString( s ); - - return *this; -} - diff --git a/src/confpairbase.h b/src/confpairbase.h deleted file mode 100644 index 2530756..0000000 --- a/src/confpairbase.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef CONF_PAIR_BASE_H -#define CONF_PAIR_BASE_H - -#include -#include -#include -#include - -class ConfPairBase -{ -public: - ConfPairBase(); - virtual ~ConfPairBase(); - - virtual void setFromString( const std::string &sStr )=0; - virtual std::string getAsString()=0; - - ConfPairBase &operator=( const std::string &s ); - -private: - -}; - -#endif diff --git a/src/conftree.cpp b/src/conftree.cpp deleted file mode 100644 index d9a3a3f..0000000 --- a/src/conftree.cpp +++ /dev/null @@ -1,9 +0,0 @@ -#include "conftree.h" - -ConfTree::ConfTree() -{ -} - -ConfTree::~ConfTree() -{ -} diff --git a/src/conftree.h b/src/conftree.h deleted file mode 100644 index 197b1ef..0000000 --- a/src/conftree.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef CONF_TREE_H -#define CONF_TREE_H - -#include - -/** - * - */ -class ConfTree -{ -public: - ConfTree(); - virtual ~ConfTree(); - -private: - -}; - -#endif diff --git a/src/connection.cpp b/src/connection.cpp deleted file mode 100644 index efef144..0000000 --- a/src/connection.cpp +++ /dev/null @@ -1,564 +0,0 @@ -#include "connection.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "exceptions.h" - -// Read buffer size...maybe fix wierd issues... -#define RBS (1024*10) - -Connection::Connection() -{ - nSocket = -1; - bActive = false; - bDisconnectMe = false; - pProtocol = NULL; -} - -Connection::~Connection() -{ - if( pProtocol != NULL ) delete pProtocol; -} - -void Connection::ensureCapacity( int nSize ) -{ - xOutputBuf.ensureCapacity( nSize ); -} - -bool Connection::appendOutput( const char *lpOutput, int nSize ) -{ - return xOutputBuf.appendData( lpOutput, nSize ); -} - -bool Connection::appendOutput( const char lOutput ) -{ - return xOutputBuf.appendData( lOutput ); -} - -bool Connection::appendOutput( const short lOutput ) -{ - return xOutputBuf.appendData( lOutput ); -} - -bool Connection::appendOutput( const int lOutput ) -{ - return xOutputBuf.appendData( lOutput ); -} - -bool Connection::appendOutput( const long lOutput ) -{ - return xOutputBuf.appendData( lOutput ); -} - -bool Connection::appendOutput( const float lOutput ) -{ - return xOutputBuf.appendData( lOutput ); -} - -bool Connection::appendOutput( const double lOutput ) -{ - return xOutputBuf.appendData( lOutput ); -} - -bool Connection::appendOutput( const unsigned char lOutput ) -{ - return xOutputBuf.appendData( lOutput ); -} - -bool Connection::appendOutput( const unsigned short lOutput ) -{ - return xOutputBuf.appendData( lOutput ); -} - -bool Connection::appendOutput( const unsigned long lOutput ) -{ - return xOutputBuf.appendData( lOutput ); -} - -bool Connection::appendOutput( const unsigned int lOutput ) -{ - return xOutputBuf.appendData( lOutput ); -} - -bool Connection::appendInput( const char *lpInput, int nSize ) -{ - return xInputBuf.appendData( lpInput, nSize ); -} - -int Connection::scanInputFor( char cTarget ) -{ - const char *lpTmp = xInputBuf.getData(); - int jMax = xInputBuf.getLength(); - - for( int j = 0; j < jMax; j++ ) - { - if( lpTmp[j] == cTarget ) - { - return j; - } - } - - return -1; -} - -const char *Connection::getOutput() -{ - return xOutputBuf.getData(); -} - -const char *Connection::getInput() -{ - return xInputBuf.getData(); -} - -void Connection::setSocket( int nNewSocket ) -{ - nSocket = nNewSocket; -} - -int Connection::getSocket() -{ - return nSocket; -} - -bool Connection::isActive() -{ - return bActive; -} - -void Connection::close() -{ - //printf("Close called, socket is: %s\n", bActive?"Active":"Inactive" ); - if( bActive ) - { - fsync( nSocket ); - ::close( nSocket ); - //printf("Socket closed.\n"); - } - bActive = false; - //nSocket = -1; - xInputBuf.clearData(); - xOutputBuf.clearData(); - if( pProtocol != NULL ) - { - delete pProtocol; - pProtocol = NULL; - } -} - -bool Connection::open( int nNewSocket ) -{ - bActive = true; - setSocket( nNewSocket ); - bDisconnectMe = false; - - return true; -} - -bool Connection::open( const char *sAddr, int nPort, int nSec ) -{ - struct sockaddr_in xServerName; - bActive = false; - - /* Create the socket. */ - nSocket = socket( PF_INET, SOCK_STREAM, 0 ); - - if( nSocket < 0 ) - { - bActive = false; - return false; - } - - // These lines set the socket to non-blocking, a good thing? - int flags; - flags = fcntl(nSocket, F_GETFL, 0); - flags |= O_NONBLOCK; - if (fcntl(nSocket, F_SETFL, flags) < 0) - { - return false; - } - - /* Connect to the server. */ - //printf("Resolving hostname (%s)...\n", sAddr ); - { - struct hostent *hostinfo; - - xServerName.sin_family = AF_INET; - xServerName.sin_port = htons( nPort ); - hostinfo = gethostbyname( sAddr ); - if (hostinfo == NULL) - { - return false; - } - xServerName.sin_addr = *(struct in_addr *) hostinfo->h_addr; - } - - //printf("Making actual connection..."); - //fflush( stdout ); - connect( - nSocket, - (struct sockaddr *)&xServerName, - sizeof(xServerName) - ); - //printf("Connected.\n"); - - bActive = true; - bDisconnectMe = false; - - if( nSec > 0 ) - { - fd_set rfds, wfds, efds; - int retval; - - FD_ZERO(&rfds); - FD_SET(nSocket, &rfds); - FD_ZERO(&wfds); - FD_SET(nSocket, &wfds); - FD_ZERO(&efds); - FD_SET(nSocket, &efds); - - struct timeval tv; - tv.tv_sec = nSec; - tv.tv_usec = 0; - - retval = select( nSocket+1, &rfds, &wfds, &efds, &tv ); - - if( retval == 0 ) - { - close(); - throw ExceptionBase("Connection timeout.\n"); - } - - } - - /* - if( ret < 0 ) - { - return false; - }*/ - - return true; -} - -int Connection::readInput() -{ - char buffer[RBS]; - int nbytes; - int nTotalRead=0; - - for(;;) - { - //memset( buffer, 0, RBS ); - - nbytes = read( nSocket, buffer, RBS ); - if( nbytes < 0 && errno != 0 && errno != EAGAIN ) - { - //printf("errno: %d, %s\n", errno, strerror( errno ) ); - /* Read error. */ - //perror("readInput"); - throw ConnectionException( excodeReadError, "Read error: %s", strerror( errno ) ); - } - else - { - if( nbytes <= 0 ) - break; - nTotalRead += nbytes; - appendInput( buffer, nbytes ); - /* Data read. */ - if( nbytes < RBS ) - { - break; - } - - /* New test, if data is divisible by RBS bytes on some libs the - * read could block, this keeps it from happening. - */ - { - fd_set rfds; - FD_ZERO(&rfds); - FD_SET(nSocket, &rfds); - struct timeval tv = { 0, 0 }; - int retval = select( nSocket+1, &rfds, NULL, NULL, &tv ); - if( retval == -1 ) - throw ConnectionException( - excodeBadReadError, - "Bad Read error" - ); - if( !FD_ISSET( nSocket, &rfds ) ) - break; - } - - } - } - - if( pProtocol != NULL && nTotalRead > 0 ) - { - pProtocol->onNewData(); - } - - return nTotalRead; -} - -bool Connection::readInput( int nSec, int nUSec, int *pnSecBack, int *pnUSecBack ) -{ - fd_set rfds, efds; - struct timeval tv, start, end; - struct timezone tz; - int retval; - - gettimeofday( &start, &tz ); - - FD_ZERO(&rfds); - FD_SET(nSocket, &rfds); - FD_ZERO(&efds); - FD_SET(nSocket, &efds); - - tv.tv_sec = nSec; - tv.tv_usec = nUSec; - - //printf("Starting at %d %d\n", nSec, nUSec ); - retval = select( nSocket+1, &rfds, NULL, NULL, &tv ); - - if( retval == -1 ) - { - // Oh my god!!! some kind of horrible problem!!!! - throw ConnectionException( excodeBadReadError, "Bad Read error"); - return false; - } - else if( retval ) - { - //printf("retval=%d, nSocket=%d,%d, sec=%d, usec=%d\n", retval, nSocket, FD_ISSET( nSocket, &rfds ), tv.tv_sec, tv.tv_usec ); - // None of them have data, but the connection is still active. - if( FD_ISSET( nSocket, &rfds ) ) - { - if( readInput() == 0 ) - { - throw ConnectionException( excodeConnectionClosed, "Connection closed"); } - } - } - - gettimeofday( &end, &tz ); - - int st, ust; - st = nSec - ( end.tv_sec - start.tv_sec ); - if( ( end.tv_usec - start.tv_usec ) > nUSec ) - { - (st)--; - ust = 1000000 - (end.tv_usec - start.tv_usec); - } - else - { - ust = nUSec - (end.tv_usec - start.tv_usec); - } - - if( st < 0 ) - { - st = ust = 0; - } - - if( pnSecBack ) - { - *pnSecBack = st; - *pnUSecBack = ust; - } - - //printf("New time: %d %d\n", *pnSecBack, *pnUSecBack ); - - return true; -} - -void Connection::waitForInput( int nBytesIn, int nSec, int nUSec ) -{ - int rlen = getInputAmnt(); - - if( rlen >= nBytesIn ) - return; - - while( rlen < nBytesIn ) - { - if( nSec == 0 && nUSec == 0 ) - { - throw ConnectionException( excodeSocketTimeout, "Timed out while waiting for %d bytes.", nBytesIn ); - } - readInput( nSec, nUSec, &nSec, &nUSec ); - rlen = getInputAmnt(); - } -} - -bool Connection::clearOutput() -{ - return xOutputBuf.clearData(); -} - -bool Connection::clearInput() -{ - return xInputBuf.clearData(); -} - -#define min( a, b ) ((asetConnection( this ); -} - -int Connection::getInputAmnt() -{ - return xInputBuf.getLength(); -} - -int Connection::getOutputAmnt() -{ - return xOutputBuf.getLength(); -} - -class Protocol *Connection::getProtocol() -{ - return pProtocol; -} - -void Connection::printInputDebug( const char *lpPrefix, FILE *fh, int nBytesMax ) -{ - printDataDebug( - (const unsigned char *)xInputBuf.getData(), - xInputBuf.getLength(), - "input", - lpPrefix, - fh, - nBytesMax - ); -} - -void Connection::printOutputDebug( const char *lpPrefix, FILE *fh, int nBytesMax ) -{ - printDataDebug( - (const unsigned char *)xOutputBuf.getData(), - xOutputBuf.getLength(), - "output", - lpPrefix, - fh, - nBytesMax - ); -} - -void Connection::printDataDebug( const unsigned char *pData, long nDataLen, const char *lpName, const char *lpPrefix, FILE *fh, int nBytesMax ) -{ - if( nBytesMax > 0 ) - { - nDataLen = (nBytesMax32 && pData[j+k]<=128)?(pData[j+k]):('.') ); - } - fprintf( fh, "\n"); - j += kmax; - if( j >= nDataLen ) break; - } - fprintf( fh, lpPrefix ); - for( int l = 0; l < 8*3+2*8+2; l++ ) fprintf( fh, (l!=8*3)?("-"):("+") ); fprintf( fh, "\n"); -} - diff --git a/src/connection.h b/src/connection.h deleted file mode 100644 index 0e991c7..0000000 --- a/src/connection.h +++ /dev/null @@ -1,411 +0,0 @@ -/**\file - * Contains the Connection class. - *@author Mike Buland - */ - -#ifndef CONNECTION_H -#define CONNECTION_H - -#include "multilog.h" -#include "flexbuf.h" -#include "protocol.h" - -/** Represents a single connection on a network. While these connections - * may be treated more or less just like files, occasionally problems arise - * when writing data at any time you feel like. Therefore you run all your - * data through a Connection, which buffers all data and makes sure no - * buffers are exceeded and nothing inappropriate for the recipient of the - * data is sent. - *@author Mike Buland - */ -class Connection -{ -public: - /** - * Construct a blank and non-connected Connection. The created object is - * not yet connected to anything, and most of the functions except open are - * unusable. - */ - Connection(); - - /** - * Destroy the connection, clean up all pending data requests and close the - * contained socket. This does not send out pending data, especially since - * such an operation could take considerable time, depending on the pending - * data and state of the receiving end. - */ - virtual ~Connection(); - - /** - * Open a connection to a remote server. This sets up this connection as - * a client instead of a server and does all of the work that needs to be - * done to actually open an INET_AF connection, which is a lot of work. - *@param sAddr The address to connect to. This can be in any format - * normally understood by your system to be an address, ip, domain name, - * etc. - *@param nPort The port number to connect to on the remote server. - *@returns True if the connection was successful and everything is setup, - * false if there were any of a dozen errors and the connection is not set. - *@todo Make this function add log entries to a standard MultiLog if - * something goes wrong. - */ - bool open( const char *sAddr, int nPort, int nSec=30 ); - - void ensureCapacity( int nSize ); - - /** Append the given data to the output. The data is presumed to be null - * terminated. To put binary data into the stream, use the other - * appendOutput function. This should be the only method used to - * communicate with the socket. - *@param lpOutput The data to add to the output queue. - *@param nSize How much data is in the lpOutput buffer. If this value - * is -1 then the program treats lpOutput as a null-terminated string. - *@returns True if everything is ok, false otherwise. - */ - bool appendOutput( const char *lpOutput, int nSize=-1 ); - - /** - * Append the character to the output. - *@param lOutput The character to add to the output queue. - *@returns True if everything is ok, false otherwise. - */ - bool appendOutput( const char lOutput ); - - /** - * Append the short to the output. - *@param lOutput The short to add to the output queue. - *@returns True if everything is ok, false otherwise. - */ - bool appendOutput( const short lOutput ); - - /** - * Append the int to the output. - *@param lOutput The int to add to the output queue. - *@returns True if everything is ok, false otherwise. - */ - bool appendOutput( const int lOutput ); - - /** - * Append the long to the output. - *@param lOutput The long to add to the output queue. - *@returns True if everything is ok, false otherwise. - */ - bool appendOutput( const long lOutput ); - - /** - * Append the float to the output. - *@param lOutput The float to add to the output queue. - *@returns True if everything is ok, false otherwise. - */ - bool appendOutput( const float lOutput ); - - /** - * Append the double to the output. - *@param lOutput The double to add to the output queue. - *@returns True if everything is ok, false otherwise. - */ - bool appendOutput( const double lOutput ); - - /** - * Append the unsigned char to the output. - *@param lOutput The unsigned char to add to the output queue. - *@returns True if everything is ok, false otherwise. - */ - bool appendOutput( const unsigned char lOutput ); - - /** - * Append the unsigned short to the output. - *@param lOutput The unsigned short to add to the output queue. - *@returns True if everything is ok, false otherwise. - */ - bool appendOutput( const unsigned short lOutput ); - - /** - * Append the unsigned int to the output. - *@param lOutput The unsigned int to add to the output queue. - *@returns True if everything is ok, false otherwise. - */ - bool appendOutput( const unsigned int lOutput ); - - /** - * Append the unsigned long to the output. - *@param lOutput The unsigned long to add to the output queue. - *@returns True if everything is ok, false otherwise. - */ - bool appendOutput( const unsigned long lOutput ); - - /** - * Writes all input data in the buffer in a dual-view ascii and hex display - * to a file. There are a number of options that also help with debugging. - *@param lpPrefix Text to be added to the begining of every line written - * out. The default is a blank string. - *@param fh The file to write the data to in text mode. This is stdout by - * default, but could be any already open file handle. - *@param nBytesMax The maximum number of bytes to write to the output. The - * amount of data can be overwhelming sometimes, so you can limit it. The - * default value is -1, which is also unlimited. - */ - void printInputDebug( const char *lpPrefix="", FILE *fh=stdout, int nBytesMax=-1 ); - - /** - * Writes all output data in the buffer in a dual-view ascii and hex display - * to a file. There are a number of options that also help with debugging. - *@param lpPrefix Text to be added to the begining of every line written - * out. The default is a blank string. - *@param fh The file to write the data to in text mode. This is stdout by - * default, but could be any already open file handle. - *@param nBytesMax The maximum number of bytes to write to the output. The - * amount of data can be overwhelming sometimes, so you can limit it. The - * default value is -1, which is also unlimited. - */ - void printOutputDebug( const char *lpPrefix="", FILE *fh=stdout, int nBytesMax=-1 ); - - /** - * This is the low-level generic function that is called by both - * printInputDebug and printOutputDebug. It works effectively just like - * both of them, except that you can give it a raw pointer to the data to - * print out. This probably doesn't belong in this class, but this was - * where I was when I needed it. - *@param pData A pointer to the data to write. This is not treated as a - * null terminated string, so make sure that the nDataLen param is set - * properly. - *@param nDataLen The number of bytes that are in pData and that you want to - * see. - *@param lpName The name of the data, this is used in the header where it - * says "Displaying nnn bytes of ." A good example would be input - * or output. - *@param lpPrefix Text to put before every line output. This just makes it - * easier to tell large blocks apart in the output. - *@param fh The file handle to write all data to. - *@param nBytesMax The maximum number of bytes. This parameter is stupid. - * If it is set to -1, then nDataLen is used, otherwise the smaller value is - * used as the number of bytes to output. - *@todo Put this function somewhere more deserving. - *@todo Remove the nBytesMax param, we need that in the other functions, - * not this one! - */ - void printDataDebug( const unsigned char *pData, long nDataLen, const char *lpName, const char *lpPrefix, FILE *fh, int nBytesMax ); - - /** Append the given data to the input. The data is presumed to be null - * terminated. To put binary data into the stream, use the other - * appendInput function. This is mainly used by internal routines. - *@param lpInput The data to add to the input queue. - *@param nSize How much data is in the lpInput buffer. If this value - * is -1 then the program treats lpOutput as a null-terminated string. - *@returns True if everything is ok, false otherwise. - */ - bool appendInput( const char *lpInput, int nSize=-1 ); - - /** Searches through the current pending input for a certain character. - * This is useful for finding out where exactly the end of a line is, for - * example, to see if a command has been entered yet. - *@param cTarget The character to search for. - *@returns The position of the target relative to the begining of the input - * or -1 if the target wasn't found. - */ - int scanInputFor( char cTarget ); - - /** Gets a pointer to the output buffer. This is mainly used by internal - * routines, and is cleared every click when data is sent out again. - *@returns A pointer to the buffer holding the pending output data. - */ - const char *getOutput(); - - /** Gets a pointer to the start of the input buffer's active data - * section. Use this to gain access to the input you need to do - * your job. - *@returns A pointer to the data in the input buffer. Do not delete this. - */ - const char *getInput(); - - /** Clears all pending output, this is mainly just used internally. - *@returns True if operation was a success, otherwise false. - */ - bool clearOutput(); - - /** Clears all pending input, weather it's been used or not. Please - * refrain from calling this during normal operation, use usedInput - * instead, it's much safer. - *@returns True if the operation was a success, false otherwise. - */ - bool clearInput(); - - /** Sets the socket that should be used internally. - *@param nNewSocket The new socket to work with. - */ - void setSocket( int nNewSocket ); - - /** Gets the handle (number) of the working socket. This can be a - * dangerous function to call, please refrain from calling it directly - * if any alternative can be found. - *@returns The number of the working socket. - */ - int getSocket(); - - /** Determines if the connection is still active. - *@returns True if the connection is active, false otherwise. - */ - bool isActive(); - - /** Clears all buffers and sets up the connection to be reused. - * Does not actually close the socket, that's handled by the - * ConnectionManager - */ - void close(); - - /** Opens a socket. Really just sets up the connection for use since - * the socket itself was created and opened by the ConnectionManager. - * This also calls setSocket so you don't have to. - *@param nNewSocket The socket to assosiate with. - */ - bool open( int nNewSocket ); - - /** - * Reads all pending input from the connection. If this is called outside - * of the ConnectionManager it will usually block indefinately waiting for - * new data. The only way to change this behaviour is to modify the socket - * low-level when you connect it manually, or, preferably use the other - * readInput function to control blocking time. - *@returns True socket is still connected, otherwise false. - */ - int readInput(); - - /** - * Reads all pending input from the connection, blocking up to nSec - * seconds and nUSec micro-seconds for the data. This uses select to - * simulate blocking, but has the same effect as standard io blocking. - * If you don't want to block, just set both values to zero. The back - * parameters are optional, set to null to not use them. The variables - * you pass in through the back parameters will contain the remaining - * time if data arrived before the max timeout was reached. - *@param nSec Max seconds to wait. - *@param nUSec Max micro-seconds to wait. - *@param pnSecBack The number of seconds remaining. - *@param pnUSecBack The number of micro-seconds remaining. - */ - bool readInput( int nSec, int nUSec, int *pnSecBack=NULL, int *pnUSecBack=NULL ); - - /** - * Waits until at least nBytesIn are read into the input buffer and ready - * to be used. Wait at most nSec seconds plus nUSec micro seconds. - * If the timeout is exceeded, this function throws an exception. If this - * function returns normally, you are guranteed to have at least nBytesIn - * bytes in your input buffer. - *@param nBytesIn Number of bytes to read. - *@param nSec The max seconds to wait. - *@param sUSec The max microseconds to wait. - */ - void waitForInput( int nBytesIn, int nSec, int nUSec ); - - /** Writes some data that is pending to the socket. - *@returns True if all data was written succesfully, false otherwise. - */ - bool writeOutput(); - - /** - * Writes all data that is pending on the socekt. - */ - bool writeAllOutput(); - - /** Determines if the connection has output waiting to go out. - *@returns true if there is pending output, otherwise false. - */ - bool hasOutput(); - - /** Sets internal flags so that this connection will be deleted next - * time through the ConnectionManager. - */ - void disconnect(); - - /** Determines if this connection is ready to be disconnected or not. - *@returns True if it is time to disconnect, false if it isn't. - */ - bool needDisconnect(); - - /** Tells the caller if there is pending input waiting to be processed. - *@returns True if there is pending input that has not been used, returns - * false if there isn't. - */ - bool hasInput(); - - /** Removes bytes from the begining of the input queue. Use this after - * getting the input and processing as much as you need to. - *@param nAmount The number of bytes used. - *@returns true if the update was successful, otherwise false. - */ - bool usedInput( int nAmount ); - - /** Sets the protocol to be used by this connection. All data in and out - * passes through the protocol object, which may process that data to - * filter out and process any special messages that may have been - * included. Everything that isn't processed can be accessed in the - * standard method. - *@param pNewProtocol A pointer to a protocol object that you want to - * use. - */ - void setProtocol( class Protocol *pNewProtocol ); - - /** Gets the number of bytes that are waiting in the input queue, the data - * that has yet to be processed. - *@returns The number of bytes in the input queue. - */ - int getInputAmnt(); - - /** Gets the number of bytes that are waiting in the output queue, the data - * that has yet to be sent to the connected socket. - *@returns The number of bytes in the input queue. - */ - int getOutputAmnt(); - - /** Gets a pointer to the protocol that is attatched to this connection - * object. This is useful to set modes, and send special commands in - * addition to the standard raw data reads and writes that are normally - * permitted. In fact, in everything besides a raw telnet protocol all - * data should be sent through the protocol and not the connection object. - *@returns A pointer to the Protocol assosiated with this connection. - */ - class Protocol *getProtocol(); - -private: - /** - * A buffer to keep data read from the socket in. This is filled in by - * the function readInput, which is automatically called by the - * ConnectionManager whenever new data is ready. - */ - FlexBuf xInputBuf; - - /** - * A buffer to keep data that should be sent to the socket. This is filled - * in by using the AppendOutput functions and is sent to the socket using - * the writeOutput function, which is automatically called every cycle by - * the ConnectionManager when there is pending data. - */ - FlexBuf xOutputBuf; - - /** - * The socket that the user is connected to. This is not the same as the - * socket number of the listening socket, this is the unique socket on the - * system that the data is coming to. - */ - int nSocket; - - /** - * True=active connection, False=connection lost - */ - bool bActive; - - /** - * True=disconnect next cycle (after data is transmitted), Flse=keep going. - */ - bool bDisconnectMe; - - /** - * A pointer to a protocol handler that can automatically process the data - * in the buffers. This is optional if you use the connections on your own - * but reccomended if you use this with the rest of the ConnectionManager - * system. - */ - class Protocol *pProtocol; -}; - -#endif diff --git a/src/connectionmanager.cpp b/src/connectionmanager.cpp deleted file mode 100644 index ea60b2b..0000000 --- a/src/connectionmanager.cpp +++ /dev/null @@ -1,397 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "connectionmanager.h" -#include - -ConnectionManager::ConnectionManager( int nInitPool ) : - xLog( MultiLog::getInstance() ) -{ - //nMasterSocket = -1; - pMonitor = NULL; - for( int j = 0; j < nInitPool; j++ ) - { - lInactive.insert( lInactive.begin(), new Connection() ); - } - FD_ZERO (&fdActive); - FD_ZERO (&fdRead); - FD_ZERO (&fdWrite); - FD_ZERO (&fdException); -} - -ConnectionManager::~ConnectionManager() -{ - std::list::const_iterator i; - for( i = lActive.begin(); i != lActive.end(); i++ ) - { - delete (*i); - } - for( i = lInactive.begin(); i != lInactive.end(); i++ ) - { - delete (*i); - } -} - -bool ConnectionManager::startServer( int nPort ) -{ - /* Create the socket and set it up to accept connections. */ - struct sockaddr_in name; - - /* Give the socket a name. */ - name.sin_family = AF_INET; - name.sin_port = htons( nPort ); - - // I think this specifies who we will accept connections from, - // a good thing to make configurable later on - name.sin_addr.s_addr = htonl( INADDR_ANY ); - - return startServer( name ); -} - -bool ConnectionManager::startServer( const char *sAddr, int nPort ) -{ - /* Create the socket and set it up to accept connections. */ - struct sockaddr_in name; - - /* Give the socket a name. */ - name.sin_family = AF_INET; - name.sin_port = htons( nPort ); - - inet_aton( sAddr, &name.sin_addr ); - - return startServer( name ); -} - -bool ConnectionManager::startServer( struct sockaddr_in &name ) -{ - /* Create the socket. */ - int nMasterSocket = socket (PF_INET, SOCK_STREAM, 0); - if (nMasterSocket < 0) - { - xLog.LineLog( MultiLog::LError, "Couldn't create a listen socket."); - return false; - } - - int opt = 1; - setsockopt( - nMasterSocket, - SOL_SOCKET, - SO_REUSEADDR, - (char *)&opt, - sizeof(opt) - ); - - if (bind (nMasterSocket, (struct sockaddr *) &name, sizeof (name)) < 0) - { - xLog.LineLog( MultiLog::LError, "Couldn't bind to the listen socket."); - return false; - } - - if (listen (nMasterSocket, 40) < 0) - { - xLog.LineLog( MultiLog::LError, "Couldn't begin listening to the server socket."); - return false; - } - - /* Initialize the set of active sockets. */ - FD_SET (nMasterSocket, &fdActive); - - sMasterSocket[nMasterSocket] = name.sin_port; - - return true; -} - -bool ConnectionManager::startServer( int nPort, int nNumTries, int nTimeout ) -{ - struct timeval xTimeout; - - for( int j = 0; j < nNumTries; j++ ) - { - xLog.LineLog( MultiLog::LStatus, "Attempting to create server socket (attempt [%d/%d])...", j+1, nNumTries ); - if( startServer( nPort ) == true ) - { - return true; - } - else if( j < nNumTries-1 ) - { - xLog.LineLog( MultiLog::LStatus, "Waiting for %d secconds to allow port to clear...", nTimeout ); - xTimeout.tv_sec = nTimeout; - xTimeout.tv_usec = 0; - if (select(0, (fd_set *) 0, (fd_set *) 0, (fd_set *) 0, &xTimeout) < 0) { - xLog.LineLog( MultiLog::LError, "Error using select to sleep for a while."); - } - usleep( nTimeout ); - } - } - - return false; -} - -bool ConnectionManager::scanConnections( int nTimeout, bool bForceTimeout ) -{ - struct timeval xTimeout; - - xTimeout.tv_sec = nTimeout / 1000000; - xTimeout.tv_usec = nTimeout % 1000000; - - /* Block until input arrives on one or more active sockets. */ - fdRead = fdActive; - fdWrite = fdActive; - fdException = fdActive; - - // We removed the write checking because it just checks to see if you *can* - // write...that's stupid, they're all open, so it always exits immediately - // if there are ANY connections there... - if( TEMP_FAILURE_RETRY( select( FD_SETSIZE, &fdRead, (fd_set *)0/*&fdWrite*/, &fdException, &xTimeout ) ) < 0 ) - { - xLog.LineLog( MultiLog::LError, "Error attempting to scan open connections."); - perror("ConnectionManager"); - return false; - } - // Now we use select to sleep as well as to scan for connections, now we - // just need to fix the fact that if there are no connections, the seccond - // select call doesn't return until there is a connection... - if( bForceTimeout ) - { - if (select(0, (fd_set *) 0, (fd_set *) 0, (fd_set *) 0, &xTimeout) < 0) { - xLog.LineLog( MultiLog::LError, "Error using select to sleep for a while."); - } - } - - /* Service all the sockets with input pending. */ - for( int i = 0; i < FD_SETSIZE; ++i ) - { - if( FD_ISSET( i, &fdRead ) ) - { - if( sMasterSocket.find( i ) != sMasterSocket.end() ) - { - addConnection( i ); - } - else - { - Connection *pCon = findActiveConnection( i ); - if( pCon == NULL ) - { - xLog.LineLog( MultiLog::LError, "A connection object was lost, or never created!"); - return false; - } - - /* Data arriving on an already-connected socket. */ - if( pCon->readInput() == 0 ) - { - xLog.LineLog( MultiLog::LStatus, "Closing connection due to disconnect."); - close( i ); - FD_CLR( i, &fdActive ); - pMonitor->onClosedConnection( pCon ); - pCon->close(); - } - else - { - // We actually read something...but the connection handles - // protocol notification, so we don't need to do anything - // here... - } - } - } - } - std::list::iterator i; - for( i = lActive.begin(); i != lActive.end(); i++ ) - { - if( (*i)->isActive() == false ) - { - std::list::iterator l = i; - i--; - lInactive.insert( lInactive.end(), *l ); - lActive.erase( l ); - continue; - } - (*i)->getProtocol()->poll(); - if( (*i)->hasOutput() ) - { - (*i)->writeOutput(); - } - if( (*i)->needDisconnect() && !(*i)->hasOutput() ) - { - int prt = (*i)->getSocket(); - close( prt ); - FD_CLR( prt, &fdActive ); - pMonitor->onClosedConnection( *i ); - (*i)->close(); - lInactive.insert( lInactive.end(), *i ); - std::list::iterator l = i; - i--; - lActive.erase( l ); - xLog.LineLog( MultiLog::LStatus, "Closing connection due to server request."); - } - } - - return true; -} - -bool ConnectionManager::shutdownServer() -{ - while( !lActive.empty() ) - { - Connection *i = *(lActive.begin()); - if( i->isActive() ) - { - pMonitor->onClosedConnection( i ); - i->close(); - lInactive.insert( lInactive.end(), i ); - lActive.erase( lActive.begin() ); - } - } -/* - for( int i = 0; i < nPoolSize; i++ ) - { - - int prt = axConPool[i].getSocket(); - close( prt ); -// FD_CLR( prt, &fdActive ); - pMonitor->onClosedConnection( &axConPool[i] ); - axConPool[i].close(); - } -*/ - std::map::iterator i; - for( i = sMasterSocket.begin(); i != sMasterSocket.end(); i++ ) - { - int nSocket = (*i).first; - shutdown( nSocket, SHUT_RDWR ); - close( nSocket ); - } - - return true; -} - -bool ConnectionManager::broadcastMessage( const char *lpData, int nExcludeSocket ) -{ - std::list::const_iterator i; - for( i = lActive.begin(); i != lActive.end(); i++ ) - { - if( (*i)->isActive() && - (*i)->getSocket() != nExcludeSocket ) - { - (*i)->appendOutput( lpData ); - } - } - - return true; -} - -bool ConnectionManager::addConnection( int nSocket ) -{ - struct sockaddr_in clientname; - size_t size; - int newSocket; - - size = sizeof( clientname ); -#ifdef __CYGWIN__ - newSocket = accept( nSocket, (struct sockaddr *) &clientname, (int *)&size ); -#else - newSocket = accept( nSocket, (struct sockaddr *) &clientname, &size ); -#endif - if( newSocket < 0 ) - { - xLog.LineLog( MultiLog::LError, "Error accepting a new connection!" ); - return false; - } -// char *tmpa = inet_ntoa(clientname.sin_addr); - char tmpa[20]; - inet_ntop( AF_INET, (void *)&clientname.sin_addr, tmpa, 20 ); - xLog.LineLog( MultiLog::LStatus, "New connection from host %s, port %hd.", tmpa, ntohs (clientname.sin_port) ); -/* - int nCnt = 0; - for( int j = 0; j < nPoolSize; j++ ) - { - if( axConPool[j].isActive() ) - { - nCnt++; - } - } - xLog.LineLog( MultiLog::LStatus, "Connections %d/%d.", nCnt, nPoolSize ); - */ -// free( tmpa ); - FD_SET( newSocket, &fdActive ); - - //void nonblock(socket_t s) - { - int flags; - - flags = fcntl(newSocket, F_GETFL, 0); - flags |= O_NONBLOCK; - if (fcntl(newSocket, F_SETFL, flags) < 0) - { - return false; - } - } - - Connection *pCon = getInactiveConnection(); - pCon->open( newSocket ); - - pMonitor->onNewConnection( pCon, (*sMasterSocket.find(nSocket)).second ); - if( pCon->getProtocol() ) - pCon->getProtocol()->onNewConnection(); - - lActive.insert( lActive.end(), pCon ); - - return true; -} - -void ConnectionManager::connect( - const char *lpAddress, - int nPort, - int nProtocolPort, - Protocol *pNewProto - ) -{ - Connection *pCon = getInactiveConnection(); - pCon->open( lpAddress, nPort ); - int nSocket = pCon->getSocket(); - FD_SET( nSocket, &fdActive ); - - pCon->setProtocol( pNewProto ); - pMonitor->onNewClientConnection( pCon, nProtocolPort ); - if( pCon->getProtocol() ) - pCon->getProtocol()->onNewClientConnection(); - - lActive.insert( lActive.end(), pCon ); -} - -Connection *ConnectionManager::getInactiveConnection() -{ - if( lInactive.empty() ) - { - return new Connection(); - } - Connection *pCon = *(lInactive.begin()); - lInactive.erase( lInactive.begin() ); - return pCon; -} - -Connection *ConnectionManager::findActiveConnection( int nSocket ) -{ - std::list::const_iterator i; - for( i = lActive.begin(); i != lActive.end(); i++ ) - { - if( (*i)->getSocket() == nSocket ) - { - return *i; - } - } - - return NULL; -} - -void ConnectionManager::setConnectionMonitor( ConnectionMonitor *pNewMonitor ) -{ - pMonitor = pNewMonitor; -} diff --git a/src/connectionmanager.h b/src/connectionmanager.h deleted file mode 100644 index cff036b..0000000 --- a/src/connectionmanager.h +++ /dev/null @@ -1,169 +0,0 @@ -/** - *@file - * Contains the ConnectionManager. - *@author Mike Buland - */ - -#ifndef CONNECTIONMANAGER_H -#define CONNECTIONMANAGER_H - -#include "multilog.h" -#include "connection.h" -#include "connectionmonitor.h" -#include -#include -#include - -/** Manges incoming network connections as a server. Creates and works with - * Connection objects. All operations are performed on TCP/IP v4 right now, - * and on a single port, although any number of connections can be handled. - *@author Mike Buland - */ -class ConnectionManager -{ -public: - /** - * Sets up the basics, like storage for the pool, and so on. This does not - * actually start a server, bind to a port, or create a connection pool. - * That's all handled by startServer(). - */ - ConnectionManager( int nInitPool=40 ); - - /** - * Cleans up everything, and even clears out all still-connected Connection - * objects. - */ - virtual ~ConnectionManager(); - - /** - * Starts a server socket and binds to it, listening for new connections. - * Unlike the version of this that takes two parameters, this listens on - * all local addresses, or the virtual 0.0.0.0 address if available, which - * is mapped to all active local addresses. - *@param nPort The port to listen on. - *@returns True if the socket was bound to the port and serving was - * started. False if there was a problem connecting to the port. - */ - bool startServer( int nPort ); - - /** - * Starts a server socket and binds to it, listening only on the address - * specified. If you want to listen to all local addresses you can enter - * "0.0.0.0" for the address, but the version of this with one parameter - * is more universal. - *@param sAddr The local ip address to bind to - *@param nPort The port to listen on. - *@returns True if the socket was bound to the port and serving was - * started. False if there was a problem connecting to the port. - */ - bool startServer( const char *sAddr, int nPort ); - - /** - * I recomend probably not using this function on your own too much, it - * does the real work of setting up a socket, but requires a properly - * prepared sackaddr_in structure. This isn't too hard, but it's easier - * to use the other startServer functions. They call this function after - * some prepwork. - *@param name A properly formed sockaddr_in structure that will not be - * modified, but describes how to listen and to what to listen. - *@returns True on success. - */ - bool startServer( struct sockaddr_in &name ); - - /** - * This is identicle to the simpler startServer function except that it - * will automatically try to connect multiple times in case the first - * attempt or two doesn't work for some reason. Initially this was - * written to compensate for server sockets staying locked after they were - * closed for a while. - *@param nPort The port to listen on. - *@param nInitPool The size of the initial connection pool. This will - * grow automatically if necesarry. - *@param nNumTries The maximum number of times to try to connect. - *@param nTimeout The amount of time to wait in-between connection - * attempts. - *@returns True if the socket was bound to the port and serving was - * started. False if there was a problem connecting to the port. - */ - bool startServer( int nPort, int nNumTries, int nTimeout ); - - /** - * Scans all open connections, halting the calling processes until data - * is received or nTimeout ms have gone by. While waiting for the timeout - * to complete the process is placed into an idle mode. - *@param nTimeout The number of millisecconds to wait if there is nothing - * to actually do. - *@param bForceTimeout If set to true, this will force the scanner to wait - * for the timout to complete before returning, even if there was pending - * data. - */ - bool scanConnections( int nTimeout, bool bForceTimeout ); - - /** Shutdown the server and all assosiated sockets. - *@returns True if every socket was closed without problem. - */ - bool shutdownServer(); - - /** Sends a message directly to every connected port. - *@param lpData A null-terminated string of data to send. - *@param nExcludeSocket An optional socket to exclude from the broadcast. - *@returns True if every socket that should have gotten the message did. - */ - bool broadcastMessage( const char *lpData, int nExcludeSocket=-1 ); - - /** Sets a monitor for the manager. The monitor is sent notifications - * whenever a socket is connected, disconnected, or whenever an error - * occurs. - *@param pNewMonitor A pointer to a preconstructed ConnectionMonitor - */ - void setConnectionMonitor( ConnectionMonitor *pNewMonitor ); - - void connect( const char *lpAddress, int nPort, int nProtocolPort, Protocol *pNewProto ); - -private: - /** - * Take care of the work of actually accepting a connection. This will - * accept the connection, set the initial modes, and add it to the master - * list of active connections, as well as fire off any messages that need - * to be handled by anything else. - *@param nSocket The handle of the listening socket that had an incoming - * connection. - *@returns True if everything worked, False otherwise. - */ - bool addConnection( int nSocket ); - - /** - * Seraches the internal lists of connections for one with a specific - * socket. - *@param nSocket The socket the connection is using for communication. - * This is the unique socket and not the one that the connection was - * initially to. - *@returns NULL if no connection was found, otherwise a pointer to a live - * Connection object. - */ - Connection *findActiveConnection( int nSocket ); - - /** - * Searches the connection pool for an object that isn't in use yet, and - * returns it, ready to be filled in and used. - *@returns An unused connection object ready for use. - *@todo Check this code over to insure that the pool grows appropriately - * when enough extra connections are detected. - */ - Connection *getInactiveConnection(); - - std::map sMasterSocket; - //int nMasterSocket; /**< The listening or server socket. */ - fd_set fdActive; /**< The active socket set. */ - fd_set fdRead; /**< The sockets ready for a read. */ - fd_set fdWrite; /**< The sockets ready for a write. */ - fd_set fdException; /**< The sockets that have gotten errors. */ - std::list lInactive; /**< The pool of inactive Connections */ - std::list lActive; /**< The pool of active Connections */ - MultiLog &xLog; /**< A handle to the active multilog. */ - - /** The ConnectionMonitor to notify of new connections. */ - ConnectionMonitor *pMonitor; -}; - -#endif diff --git a/src/connectionmonitor.cpp b/src/connectionmonitor.cpp deleted file mode 100644 index 4f90ee6..0000000 --- a/src/connectionmonitor.cpp +++ /dev/null @@ -1,10 +0,0 @@ -#include "connectionmonitor.h" - -ConnectionMonitor::ConnectionMonitor() -{ -} - -ConnectionMonitor::~ConnectionMonitor() -{ -} - diff --git a/src/connectionmonitor.h b/src/connectionmonitor.h deleted file mode 100644 index 9910556..0000000 --- a/src/connectionmonitor.h +++ /dev/null @@ -1,47 +0,0 @@ -/**@file - * Describes the ConnectionMonitor class. - */ -#ifndef CONNECTIONMONITOR_H -#define CONNECTIONMONITOR_H - -#include "connection.h" - -/** Connection Monitor defines the base class of the objects that will be - * notified whenever a connection is created or destroyed. - *@author Mike Buland - */ -class ConnectionMonitor -{ -public: - /** - * This is only here for completeness. It does nothing. - */ - ConnectionMonitor(); - - /** - * This is only here for completeness. It does nothing. - */ - virtual ~ConnectionMonitor(); - - /** Receives the notification that new connection was received. - *@param pCon The connection that was created. - *@param nSocket The socket that the client connected to, used to determine - * which protocol to apply. - *@returns Should return a true value if everything is OK, a false to - * force a shutdown. - */ - virtual bool onNewConnection( Connection *pCon, int nPort ) = 0; - virtual bool onNewClientConnection( Connection *pCon, int nPort ) - { - return onNewConnection( pCon, nPort ); - }; - - /** Receives the notification that a connection was closed. - *@param pCon The connection that was closed. - *@returns Should return a true value if everything is OK, a false to - * force a shutdown. - */ - virtual bool onClosedConnection( Connection *pCon ) = 0; -}; - -#endif diff --git a/src/exceptionbase.cpp b/src/exceptionbase.cpp deleted file mode 100644 index f3d22da..0000000 --- a/src/exceptionbase.cpp +++ /dev/null @@ -1,70 +0,0 @@ -#include "exceptionbase.h" -#include - -ExceptionBase::ExceptionBase( const char *lpFormat, ... ) throw() : - nErrorCode( 0 ), - sWhat( NULL ) -{ - va_list ap; - - va_start(ap, lpFormat); - setWhat( lpFormat, ap ); - va_end(ap); -} - -ExceptionBase::ExceptionBase( int nCode, const char *lpFormat, ... ) throw() : - nErrorCode( nCode ), - sWhat( NULL ) -{ - va_list ap; - - va_start(ap, lpFormat); - setWhat( lpFormat, ap ); - va_end(ap); -} - -ExceptionBase::ExceptionBase( int nCode ) throw() : - nErrorCode( nCode ), - sWhat( NULL ) -{ -} - -ExceptionBase::~ExceptionBase() throw() -{ - if( sWhat ) - { - delete[] sWhat; - sWhat = NULL; - } -} - -void ExceptionBase::setWhat( const char *lpFormat, va_list &vargs ) -{ - if( sWhat ) delete[] sWhat; - int nSize; - - nSize = vsnprintf( NULL, 0, lpFormat, vargs ); - sWhat = new char[nSize+1]; - vsnprintf( sWhat, nSize+1, lpFormat, vargs ); -} - -void ExceptionBase::setWhat( const char *lpText ) -{ - if( sWhat ) delete[] sWhat; - int nSize; - - nSize = strlen( lpText ); - sWhat = new char[nSize+1]; - strcpy( sWhat, lpText ); -} - -const char *ExceptionBase::what() const throw() -{ - return sWhat; -} - -int ExceptionBase::getErrorCode() -{ - return nErrorCode; -} - diff --git a/src/exceptionbase.h b/src/exceptionbase.h deleted file mode 100644 index 6f1eca7..0000000 --- a/src/exceptionbase.h +++ /dev/null @@ -1,105 +0,0 @@ -#ifndef EXCEPTION_BASE_H -#define EXCEPTION_BASE_H - -#include -#include -#include - -/** - * A generalized Exception base class. This is nice for making general and - * flexible child classes that can create new error code classes. - */ -class ExceptionBase : public std::exception -{ -public: - /** - * Construct an exception with an error code of zero, but with a - * description. The use of this is not reccomended most of the time, it's - * generally best to include an error code with the exception so your - * program can handle the exception in a better way. - * @param sFormat The format of the text. See printf for more info. - */ - ExceptionBase( const char *sFormat, ... ) throw(); - - /** - * - * @param nCode - * @param sFormat - */ - ExceptionBase( int nCode, const char *sFormat, ... ) throw(); - - /** - * - * @param nCode - * @return - */ - ExceptionBase( int nCode=0 ) throw(); - - /** - * - * @return - */ - virtual ~ExceptionBase() throw(); - - /** - * - * @return - */ - virtual const char *what() const throw(); - - /** - * - * @return - */ - int getErrorCode(); - - /** - * - * @param lpFormat - * @param vargs - */ - void setWhat( const char *lpFormat, va_list &vargs ); - - /** - * - * @param lpText - */ - void setWhat( const char *lpText ); - -private: - int nErrorCode; /**< The code for the error that occured. */ - char *sWhat; /**< The text string telling people what went wrong. */ -}; - -#define subExceptionDecl( name ) \ -class name : public ExceptionBase \ -{ \ - public: \ - name( const char *sFormat, ... ) throw (); \ - name( int nCode, const char *sFormat, ... ) throw(); \ - name( int nCode=0 ) throw (); \ -}; - -#define subExceptionDef( name ) \ -name::name( const char *lpFormat, ... ) throw() : \ - ExceptionBase( 0 ) \ -{ \ - va_list ap; \ - va_start( ap, lpFormat ); \ - setWhat( lpFormat, ap ); \ - va_end( ap ); \ -} \ -name::name( int nCode, const char *lpFormat, ... ) throw() : \ - ExceptionBase( nCode ) \ -{ \ - va_list ap; \ - va_start( ap, lpFormat ); \ - setWhat( lpFormat, ap ); \ - va_end( ap ); \ -} \ -name::name( int nCode ) throw() : \ - ExceptionBase( nCode ) \ -{ \ -} - -#endif diff --git a/src/exceptions.cpp b/src/exceptions.cpp deleted file mode 100644 index ce79a5e..0000000 --- a/src/exceptions.cpp +++ /dev/null @@ -1,8 +0,0 @@ -#include "exceptions.h" -#include - -subExceptionDef( XmlException ) -subExceptionDef( FileException ) -subExceptionDef( ConnectionException ) -subExceptionDef( PluginException ) - diff --git a/src/exceptions.h b/src/exceptions.h deleted file mode 100644 index 0ab2b15..0000000 --- a/src/exceptions.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef EXCEPTIONS_H -#define EXCEPTIONS_H - -#include "exceptionbase.h" -#include - -subExceptionDecl( XmlException ) -subExceptionDecl( FileException ) -subExceptionDecl( ConnectionException ) -subExceptionDecl( PluginException ) - -enum eFileException -{ - excodeEOF -}; - -enum eConnectionException -{ - excodeReadError, - excodeBadReadError, - excodeConnectionClosed, - excodeSocketTimeout -}; - -#endif diff --git a/src/flexbuf.cpp b/src/flexbuf.cpp deleted file mode 100644 index 6d55294..0000000 --- a/src/flexbuf.cpp +++ /dev/null @@ -1,229 +0,0 @@ -#include "flexbuf.h" -#include - -FlexBuf::FlexBuf() -{ - lpBuf = new char[1024]; - nLastChar = 0; - nFirstChar = 0; - nSize = 1024; - nFill = 0; - clearData(); -} - -FlexBuf::~FlexBuf() -{ - delete[] lpBuf; -} - -bool FlexBuf::appendData( const char *lpData, int nDSize ) -{ - int nStrLen; - if( nDSize < 0 ) - { - nStrLen = strlen( lpData ); - } - else - { - nStrLen = nDSize; - } - - if( nLastChar + nStrLen + 1 > nSize ) - { - if( nFill + nStrLen + 1 < nSize ) - { - memcpy( lpBuf, lpBuf+nFirstChar, nFill ); - nLastChar -= nFirstChar; - nFirstChar = 0; - } - else - { - nSize += nStrLen+1; - char *lpNewBuf = new char[nSize]; - memcpy( lpNewBuf, lpBuf+nFirstChar, nFill ); - delete[] lpBuf; - lpBuf = lpNewBuf; - nLastChar -= nFirstChar; - nFirstChar = 0; - } - } - - memcpy( &lpBuf[nLastChar], lpData, nStrLen ); - nLastChar += nStrLen; - nFill += nStrLen; - lpBuf[nLastChar] = '\0'; - - return true; -} - -bool FlexBuf::appendData( const char lData ) -{ - if( nLastChar + 2 > nSize ) - { - if( nFill+2 < nSize ) - { - memcpy( lpBuf, lpBuf+nFirstChar, nFill ); - nLastChar -= nFirstChar; - nFirstChar = 0; - } - else - { - nSize += 1024; - char *lpNewBuf = new char[nSize]; - memcpy( lpNewBuf, lpBuf+nFirstChar, nFill ); - delete[] lpBuf; - lpBuf = lpNewBuf; - nLastChar -= nFirstChar; - nFirstChar = 0; - } - } - - lpBuf[nLastChar] = lData; - nLastChar++; - nFill++; - lpBuf[nLastChar] = '\0'; - - return true; -} - -bool FlexBuf::appendData( const short lData ) -{ - return appendData( (const char *)&lData, sizeof(short) ); -} - -bool FlexBuf::appendData( const int lData ) -{ - return appendData( (const char *)&lData, sizeof(int) ); -} - -bool FlexBuf::appendData( const long lData ) -{ - return appendData( (const char *)&lData, sizeof(long) ); -} - -bool FlexBuf::appendData( const float lData ) -{ - return appendData( (const char *)&lData, sizeof(float) ); -} - -bool FlexBuf::appendData( const double lData ) -{ - return appendData( (const char *)&lData, sizeof(double) ); -} - -bool FlexBuf::appendData( const unsigned char lData ) -{ - return appendData( (const char)lData ); -} - -bool FlexBuf::appendData( const unsigned short lData ) -{ - return appendData( (const char *)&lData, sizeof(short) ); -} - -bool FlexBuf::appendData( const unsigned long lData ) -{ - return appendData( (const char *)&lData, sizeof(long) ); -} - -bool FlexBuf::appendData( const unsigned int lData ) -{ - return appendData( (const char *)&lData, sizeof(int) ); -} - -bool FlexBuf::clearData() -{ - nFirstChar = nLastChar = nFill = 0; - lpBuf[nLastChar] = '\0'; - - return true; -} - -const char *FlexBuf::getData() -{ - return (lpBuf+nFirstChar); -} - -int FlexBuf::getLength() -{ - return nFill; -} - -int FlexBuf::getCapacity() -{ - return nSize; -} - -bool FlexBuf::usedData( int nAmount ) -{ - // Remove from the end if negative - if( nAmount < 0 ) - { - if( nFill+nAmount < 0 ) - { - nFill = nFirstChar = nLastChar = 0; - return true; - } - nLastChar += nAmount; - nFill += nAmount; - return true; - } - if( nAmount > nFill ) - { - nAmount = nSize; -// return false; - } - - //nLastChar -= nAmount; - nFirstChar += nAmount; - nFill -= nAmount; - - if( nFill == 0 ) - { - nFirstChar = nLastChar = 0; - } - - //if( nLastChar > 0 ) - //{ - //memmove( lpBuf, &lpBuf[nAmount], nLastChar ); - //} - - return true; -} - -int FlexBuf::findChar( char cTarget ) -{ - for( int j = nFirstChar; j < nLastChar; j++ ) - { - if( lpBuf[j] == cTarget ) - { - return j; - } - } - - return -1; -} - -void FlexBuf::ensureCapacity( int nAmount ) -{ - if( nLastChar + nAmount + 1 > nSize ) - { - if( nFill + nAmount + 1 < nSize ) - { - memcpy( lpBuf, lpBuf+nFirstChar, nFill ); - nLastChar -= nFirstChar; - nFirstChar = 0; - } - else - { - nSize += nAmount+1; - char *lpNewBuf = new char[nSize]; - memcpy( lpNewBuf, lpBuf+nFirstChar, nFill ); - delete[] lpBuf; - lpBuf = lpNewBuf; - nLastChar -= nFirstChar; - nFirstChar = 0; - } - } -} - diff --git a/src/flexbuf.h b/src/flexbuf.h deleted file mode 100644 index 7d7f11a..0000000 --- a/src/flexbuf.h +++ /dev/null @@ -1,162 +0,0 @@ -/**\flexbuf.h - * Describes the FlexBuf class. - *@author Mike Buland - */ - -#ifndef FLEXBUF_H -#define FLEXBUF_H - -/** Stores any amount of data, but starts small, growing as necesarry. - * It is optimized to work with stream type situations, with data being - * added to the end while it is being taken from the begning. - *@todo Set this class up to auto-shrink back to a specified sized buffer each - * time it has shrunk below that for enough operations. - *@author Mike Buland - */ -class FlexBuf -{ -public: - /** - * Construct a blank FlexBuf containing about 1k of buffer space. - */ - FlexBuf(); - - /** - * Clean up the FlexBuf, delete all buffers. - */ - virtual ~FlexBuf(); - - /** Appends a whole string of data to the buffer. The string - * must be null terminated. - *@param lpData The data to append to the buffer. - *@param nDSize The size of the data described by lpData. If this - * value is -1 lpData is treated as a null-terminated string. - *@returns True if no problems occured, false otherwise. - */ - bool appendData( const char *lpData, int nDSize=-1 ); - - /** Appends a single character to the end of the buffer. - *@param lData The character to append to the buffer. - *@returns True if no problems occured, false otherwise. - */ - bool appendData( const char lData ); - - /** - * Append the short to the buffer. - *@param lData The short to add to the buffer queue. - *@returns True if everything is ok, false otherwise. - */ - bool appendData( const short lData ); - - /** - * Append the int to the buffer. - *@param lData The int to add to the buffer queue. - *@returns True if everything is ok, false otherwise. - */ - bool appendData( const int lData ); - - /** - * Append the long to the buffer. - *@param lData The long to add to the buffer queue. - *@returns True if everything is ok, false otherwise. - */ - bool appendData( const long lData ); - - /** - * Append the float to the buffer. - *@param lData The float to add to the buffer queue. - *@returns True if everything is ok, false otherwise. - */ - bool appendData( const float lData ); - - /** - * Append the double to the buffer. - *@param lData The double to add to the buffer queue. - *@returns True if everything is ok, false otherwise. - */ - bool appendData( const double lData ); - - /** - * Append the unsigned char to the buffer. - *@param lData The unsigned char to add to the buffer queue. - *@returns True if everything is ok, false otherwise. - */ - bool appendData( const unsigned char lData ); - - /** - * Append the unsigned short to the buffer. - *@param lData The unsigned short to add to the buffer queue. - *@returns True if everything is ok, false otherwise. - */ - bool appendData( const unsigned short lData ); - - /** - * Append the unsigned int to the buffer. - *@param lData The unsigned int to add to the buffer queue. - *@returns True if everything is ok, false otherwise. - */ - bool appendData( const unsigned int lData ); - - /** - * Append the unsigned long to the buffer. - *@param lData The unsigned long to add to the buffer queue. - *@returns True if everything is ok, false otherwise. - */ - bool appendData( const unsigned long lData ); - - /** Removes all pending data from the buffer. - *@returns True if no problems occured, false otherwise. - */ - bool clearData(); - - /** Gets a pointer to the internal buffer, at the begining of the current - * data stream. - *@returns A pointer to the internal data buffer. - */ - const char *getData(); - - /** Gets the length of the current buffer (how much data is really in the - * buffer, not it's current capacity, for that check getCapacity) - *@returns The length of the current buffer. - */ - int getLength(); - - /** Gets the current capacity of the FlexBuf. If the size nears this value - * then the entire buffer is resized to accomidate more data. - *@returns The current capacity of the FlexBuf. - */ - int getCapacity(); - - /** - * Removes nAmount bytes from the begning of the buffer. Actually, if - * nAmount happens to be negative it will remove tha absolute value of - * nValue bytes from the end of the buffer, like the old delData command. - *@param nAmount The number of bytes used. - *@returns True if everything was successful, false if there was an error. - */ - bool usedData( int nAmount ); - - /** Finds the first instance of the given character in the buffer and - * returns an index to it. - *@param cTarget The character you're looking for. - *@returns The index of the first instance of the given character, or - * -1 if it just wasn't found. - */ - int findChar( char cTarget ); - - void ensureCapacity( int nAmount ); - -private: - /** The raw storage location of the FlexBuf. */ - char *lpBuf; - /** The real size of the FlexBuf. */ - int nSize; - /** Where the last char is. */ - int nLastChar; - /** Where the first char is. */ - int nFirstChar; - /** The amount of real data in the FlexBuf. This is effectively nLastChar-nFirstChar. */ - int nFill; -}; - -#endif diff --git a/src/formula.cpp b/src/formula.cpp deleted file mode 100644 index cf63cf3..0000000 --- a/src/formula.cpp +++ /dev/null @@ -1,262 +0,0 @@ -#include "formula.h" - -subExceptionDef( ParseException ); - -Formula::Formula() -{ - hVars["pi"] = M_PI; - hVars["e"] = M_E; - - hFunc["sin"] = FuncSin(); -} - -Formula::~Formula() -{ -} - -double Formula::run( char *sFormula ) -{ - for(;;) - { - uint8_t tNum = nextToken( &sFormula ); - if( tNum == symEOS ) - break; - else if( tNum == symSubtract ) - { - tNum = nextToken( &sFormula ); - if( tNum != symNumber ) - throw ParseException("Unary minus must be followed by a number, " - "variable, function, or parenthesis."); - sValue.top() = -sValue.top(); - } - else if( tNum == symOpenParen ) - { - sOper.push( tNum ); - continue; - } - -oppart: uint8_t tOpr = nextToken( &sFormula ); - if( tOpr == symEOS ) - { - //printf("EOS "); - reduce(); - return sValue.top(); - break; - } - if( !sOper.empty() && getPrec( sOper.top() ) > getPrec( tOpr ) ) - { - reduce(); - } - if( tOpr != symCloseParen ) - { - sOper.push( tOpr ); - } - else - { - reduce( true ); - goto oppart; - } - } - return sValue.top(); -} - -void Formula::reduce( bool bCloseParen ) -{ - while( !sOper.empty() ) - { - uint8_t nOpr = sOper.top(); - if( nOpr == symOpenParen ) - { - //printf("Found ( stopping reduction.\n"); - if( bCloseParen == true ) - sOper.pop(); - return; - } - sOper.pop(); - - double dTop = sValue.top(); - sValue.pop(); - - switch( nOpr ) - { - case symAdd: - //printf("%f + %f = %f\n", sValue.top(), dTop, sValue.top()+dTop ); - sValue.top() += dTop; - break; - - case symSubtract: - //printf("%f - %f = %f\n", sValue.top(), dTop, sValue.top()-dTop ); - sValue.top() -= dTop; - break; - - case symMultiply: - //printf("%f * %f = %f\n", sValue.top(), dTop, sValue.top()*dTop ); - sValue.top() *= dTop; - break; - - case symDivide: - //printf("%f / %f = %f\n", sValue.top(), dTop, sValue.top()/dTop ); - sValue.top() /= dTop; - break; - - case symExponent: - //printf("%f ^ %f = %f\n", sValue.top(), dTop, pow(sValue.top(),dTop) ); - sValue.top() = pow( sValue.top(), dTop ); - break; - - case symModulus: - //printf("%f %% %f = %f\n", sValue.top(), dTop, fmod(sValue.top(),dTop) ); - sValue.top() = fmod( sValue.top(), dTop ); - break; - } - } - - if( bCloseParen == true ) - { - throw ParseException("Close-paren found without matching open-paren."); - } -} - -uint8_t Formula::getPrec( uint8_t nOper ) -{ - switch( nOper ) - { - case symNumber: - case symVariable: - case symOpenParen: - case symCloseParen: - return 0; - - case symAdd: - case symSubtract: - return 1; - - case symMultiply: - case symDivide: - case symModulus: - return 2; - - case symExponent: - return 3; - - default: - return 0; - } -} - -uint8_t Formula::nextToken( char **sBuf ) -{ - for(;;) - { - char cbuf = **sBuf; - ++(*sBuf); - switch( cbuf ) - { - case '+': - return symAdd; - - case '-': - return symSubtract; - - case '*': - return symMultiply; - - case '/': - return symDivide; - - case '^': - return symExponent; - - case '%': - return symModulus; - - case '(': - return symOpenParen; - - case ')': - return symCloseParen; - - case ' ': - case '\t': - case '\n': - case '\r': - break; - - case '\0': - return symEOS; - - default: - if( cbuf == '.' || (cbuf >= '0' && cbuf <= '9') ) - { - char num[50]={cbuf}; - int nPos = 1; - bool bDot = false; - - for(;;) - { - cbuf = **sBuf; - if( cbuf == '.' ) - { - if( bDot == false ) - bDot = true; - else - throw ParseException( - "Numbers cannot have more than one " - ". in them." - ); - } - if( cbuf == '.' || (cbuf >= '0' && cbuf <= '9') ) - { - num[nPos++] = cbuf; - } - else - { - num[nPos] = '\0'; - sValue.push( strtod( num, NULL ) ); - return symNumber; - } - ++(*sBuf); - } - } - else if( (cbuf >= 'a' && cbuf <= 'z') || - (cbuf >= 'A' && cbuf <= 'Z') || - (cbuf == '_') ) - { - char tok[50]={cbuf}; - int nPos = 1; - - for(;;) - { - cbuf = **sBuf; - if( (cbuf >= 'a' && cbuf <= 'z') || - (cbuf >= 'A' && cbuf <= 'Z') || - (cbuf >= '0' && cbuf <= '9') || - cbuf == '_' || cbuf == '.' || cbuf == ':' ) - { - tok[nPos++] = cbuf; - } - else - { - tok[nPos] = '\0'; - //printf("Checking variable \"%s\"\n", tok ); - try - { - sValue.push( hVars[tok] ); - return symNumber; - } - catch( HashException &e ) - { - throw ParseException( - "No variable named \"%s\" exists.", - tok - ); - } - } - ++(*sBuf); - } - } - break; - } - } -} - diff --git a/src/formula.h b/src/formula.h deleted file mode 100644 index 939eb09..0000000 --- a/src/formula.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef FORMULA_H -#define FORMULA_H - -#include - -#include -#include -#include "sbuffer.h" - -#include "exceptionbase.h" -#include "hash.h" - -subExceptionDecl( ParseException ); - -/** - * Implements a very simple formula parser that allows use of variables and - * custom functions. This is based on a simple calculator-type parser that - * executes as it processes, accounting for operator precedence and grouping. - */ -class Formula -{ -public: - Formula(); - virtual ~Formula(); - - double run( char *sFormula ); - - typedef Hash varHash; - varHash hVars; - - typedef struct Func - { - double operator()( double x ) - { - return 0.0; - } - } Func; - - typedef Hash funcHash; - funcHash hFunc; - - typedef struct FuncSin : Func - { - double operator()( double x ) - { - return sin( x ); - } - } FuncSin; - -private: - enum - { - symEOS, - symAdd, - symSubtract, - symMultiply, - symDivide, - symOpenParen, - symCloseParen, - symNumber, - symVariable, - symExponent, - symModulus - }; - - typedef uint8_t symType; - - std::stack sOper; - std::stack sValue; - -private: - symType getPrec( symType nOper ); - symType nextToken( char **sBuf ); - void reduce( bool bCloseParen = false ); -}; - -#endif diff --git a/src/fstring.cpp b/src/fstring.cpp deleted file mode 100644 index 82d024d..0000000 --- a/src/fstring.cpp +++ /dev/null @@ -1,13 +0,0 @@ -#include "fstring.h" -#include "hash.h" - -template<> uint32_t __calcHashCode( const FString &k ) -{ - return __calcHashCode( k.c_str() ); -} - -template<> bool __cmpHashKeys( const FString &a, const FString &b ) -{ - return a == b; -} - diff --git a/src/fstring.h b/src/fstring.h deleted file mode 100644 index c5397cc..0000000 --- a/src/fstring.h +++ /dev/null @@ -1,651 +0,0 @@ -#ifndef F_STRING_H -#define F_STRING_H - -#include -#include -#include "serializable.h" -#include "serializer.h" - -template< typename chr > -struct FStringChunk -{ - long nLength; - chr *pData; - FStringChunk *pNext; -}; - -/** - * Flexible String class. This class was designed with string passing and - * generation in mind. Like the standard string class you can specify what - * datatype to use for each character. Unlike the standard string class, - * collection of appended and prepended terms is done lazily, making long - * operations that involve many appends very inexpensive. In addition internal - * ref-counting means that if you pass strings around between functions there's - * almost no overhead in time or memory since a reference is created and no - * data is actually copied. This also means that you never need to put any - * FBasicString into a ref-counting container class. - */ -template< typename chr, typename chralloc=std::allocator, typename chunkalloc=std::allocator > > -class FBasicString : public Serializable -{ -#ifndef VALTEST -#define cpy( dest, src, size ) memcpy( dest, src, size*sizeof(chr) ) -#endif -private: - typedef struct FStringChunk Chunk; - typedef struct FBasicString MyType; - -public: - FBasicString() : - nLength( 0 ), - pnRefs( NULL ), - pFirst( NULL ), - pLast( NULL ) - { - } - - FBasicString( const chr *pData ) : - nLength( 0 ), - pnRefs( NULL ), - pFirst( NULL ), - pLast( NULL ) - { - append( pData ); - } - - FBasicString( const chr *pData, long nLength ) : - nLength( 0 ), - pnRefs( NULL ), - pFirst( NULL ), - pLast( NULL ) - { - append( pData, nLength ); - } - - FBasicString( const MyType &rSrc ) : - nLength( 0 ), - pnRefs( NULL ), - pFirst( NULL ), - pLast( NULL ) - { - // Here we have no choice but to copy, since the other guy is a const. - // In the case that the source were flat, we could get a reference, it - // would make some things faster, but not matter in many other cases. - - joinShare( rSrc ); - //copyFrom( rSrc ); - } - - FBasicString( const MyType &rSrc, long nLength ) : - nLength( 0 ), - pnRefs( NULL ), - pFirst( NULL ), - pLast( NULL ) - { - append( rSrc.pFirst->pData, nLength ); - } - - FBasicString( const MyType &rSrc, long nStart, long nLength ) : - nLength( 0 ), - pnRefs( NULL ), - pFirst( NULL ), - pLast( NULL ) - { - append( rSrc.pFirst->pData+nStart, nLength ); - } - - FBasicString( long nSize ) : - nLength( nSize ), - pnRefs( NULL ), - pFirst( NULL ), - pLast( NULL ) - { - pFirst = pLast = newChunk( nSize ); - } - - virtual ~FBasicString() - { - clear(); - } - - void append( const chr *pData ) - { - long nLen; - for( nLen = 0; pData[nLen] != (chr)0; nLen++ ); - - Chunk *pNew = newChunk( nLen ); - cpy( pNew->pData, pData, nLen ); - - appendChunk( pNew ); - } - - void append( const chr *pData, long nLen ) - { - Chunk *pNew = newChunk( nLen ); - - cpy( pNew->pData, pData, nLen ); - - appendChunk( pNew ); - } - - void prepend( const chr *pData ) - { - long nLen; - for( nLen = 0; pData[nLen] != (chr)0; nLen++ ); - - Chunk *pNew = newChunk( nLen ); - cpy( pNew->pData, pData, nLen ); - - prependChunk( pNew ); - } - - void prepend( const chr *pData, long nLen ) - { - Chunk *pNew = newChunk( nLen ); - - cpy( pNew->pData, pData, nLen ); - - prependChunk( pNew ); - } - - void clear() - { - realClear(); - } - - void resize( long nNewSize ) - { - if( nLength == nNewSize ) - return; - - flatten(); - - Chunk *pNew = newChunk( nNewSize ); - long nNewLen = (nNewSizepData, pFirst->pData, nNewLen ); - pNew->pData[nNewLen] = (chr)0; - aChr.deallocate( pFirst->pData, pFirst->nLength+1 ); - aChunk.deallocate( pFirst, 1 ); - pFirst = pLast = pNew; - nLength = nNewSize; - } - - long getSize() const - { - return nLength; - } - - chr *getStr() - { - if( pFirst == NULL ) - return NULL; - - flatten(); - return pFirst->pData; - } - - const chr *getStr() const - { - if( pFirst == NULL ) - return NULL; - - flatten(); - return pFirst->pData; - } - - chr *c_str() - { - if( pFirst == NULL ) - return NULL; - - flatten(); - return pFirst->pData; - } - - const chr *c_str() const - { - if( pFirst == NULL ) - return NULL; - - flatten(); - return pFirst->pData; - } - - MyType &operator +=( const chr *pData ) - { - append( pData ); - - return (*this); - } - - MyType &operator +=( const MyType &rSrc ) - { - rSrc.flatten(); - append( rSrc.pFirst->pData, rSrc.nLength ); - - return (*this); - } - - MyType &operator +=( const chr pData ) - { - chr tmp[2] = { pData, (chr)0 }; - append( tmp ); - - return (*this); - } - - MyType &operator =( const chr *pData ) - { - clear(); - append( pData ); - - return (*this); - } - - MyType &operator =( const MyType &rSrc ) - { - //if( rSrc.isFlat() ) - //{ - joinShare( rSrc ); - //} - //else - //{ - // copyFrom( rSrc ); - //} - // - - return (*this); - } - - bool operator ==( const chr *pData ) const - { - if( pFirst == NULL ) { - if( pData == NULL ) - return true; - return false; - } - - flatten(); - const chr *a = pData; - chr *b = pFirst->pData; - for( ; *a!=(chr)0; a++, b++ ) - { - if( *a != *b ) - return false; - } - - return true; - } - - bool operator ==( const MyType &pData ) const - { - if( pFirst == pData.pFirst ) - return true; - if( pFirst == NULL ) - return false; - - flatten(); - pData.flatten(); - const chr *a = pData.pFirst->pData; - chr *b = pFirst->pData; - for( ; *a!=(chr)0; a++, b++ ) - { - if( *a != *b ) - return false; - } - - return true; - } - - bool operator !=(const chr *pData ) const - { - return !(*this == pData); - } - - bool operator !=(const MyType &pData ) const - { - return !(*this == pData); - } - - chr &operator[]( long nIndex ) - { - flatten(); - - return pFirst->pData[nIndex]; - } - - const chr &operator[]( long nIndex ) const - { - flatten(); - - return pFirst->pData[nIndex]; - } - - bool isWS( long nIndex ) const - { - flatten(); - - return pFirst->pData[nIndex]==' ' || pFirst->pData[nIndex]=='\t' - || pFirst->pData[nIndex]=='\r' || pFirst->pData[nIndex]=='\n'; - } - - bool isAlpha( long nIndex ) const - { - flatten(); - - return (pFirst->pData[nIndex] >= 'a' && pFirst->pData[nIndex] <= 'z') - || (pFirst->pData[nIndex] >= 'A' && pFirst->pData[nIndex] <= 'Z'); - } - - void toLower() - { - flatten(); - unShare(); - - for( long j = 0; j < nLength; j++ ) - { - if( pFirst->pData[j] >= 'A' && pFirst->pData[j] <= 'Z' ) - pFirst->pData[j] -= 'A'-'a'; - } - } - - void toUpper() - { - flatten(); - unShare(); - - for( long j = 0; j < nLength; j++ ) - { - if( pFirst->pData[j] >= 'a' && pFirst->pData[j] <= 'z' ) - pFirst->pData[j] += 'A'-'a'; - } - } - - void serialize( class Serializer &ar ) - { - if( ar.isLoading() ) - { - clear(); - long nLen; - ar >> nLen; - - Chunk *pNew = newChunk( nLen ); - ar.read( pNew->pData, nLen*sizeof(chr) ); - appendChunk( pNew ); - } - else - { - flatten(); - - ar << nLength; - ar.write( pFirst->pData, nLength*sizeof(chr) ); - } - } - -private: - void flatten() const - { - if( isFlat() ) - return; - - if( pFirst == NULL ) - return; - - unShare(); - - Chunk *pNew = newChunk( nLength ); - chr *pos = pNew->pData; - Chunk *i = pFirst; - for(;;) - { - cpy( pos, i->pData, i->nLength ); - pos += i->nLength; - i = i->pNext; - if( i == NULL ) - break; - } - realClear(); - - pLast = pFirst = pNew; - nLength = pNew->nLength; - } - - void realClear() const - { - if( pFirst == NULL ) - return; - - if( isShared() ) - { - decRefs(); - } - else - { - Chunk *i = pFirst; - for(;;) - { - Chunk *n = i->pNext; - aChr.deallocate( i->pData, i->nLength+1 ); - aChunk.deallocate( i, 1 ); - if( n == NULL ) - break; - i = n; - } - pFirst = pLast = NULL; - nLength = 0; - } - } - - void copyFrom( const FBasicString &rSrc ) - { - if( rSrc.pFirst == NULL ) - return; - - decRefs(); - - Chunk *pNew = newChunk( rSrc.nLength ); - chr *pos = pNew->pData; - Chunk *i = rSrc.pFirst; - for(;;) - { - cpy( pos, i->pData, i->nLength ); - pos += i->nLength; - i = i->pNext; - if( i == NULL ) - break; - } - clear(); - - appendChunk( pNew ); - } - - bool isFlat() const - { - return (pFirst == pLast); - } - - bool isShared() const - { - return (pnRefs != NULL); - } - - Chunk *newChunk() const - { - Chunk *pNew = aChunk.allocate( 1 ); - pNew->pNext = NULL; - return pNew; - } - - Chunk *newChunk( long nLen ) const - { - Chunk *pNew = aChunk.allocate( 1 ); - pNew->pNext = NULL; - pNew->nLength = nLen; - pNew->pData = aChr.allocate( nLen+1 ); - pNew->pData[nLen] = (chr)0; - return pNew; - } - - void appendChunk( Chunk *pNewChunk ) - { - unShare(); - - if( pFirst == NULL ) - pLast = pFirst = pNewChunk; - else - { - pLast->pNext = pNewChunk; - pLast = pNewChunk; - } - - nLength += pNewChunk->nLength; - } - - void prependChunk( Chunk *pNewChunk ) - { - unShare(); - - if( pFirst == NULL ) - pLast = pFirst = pNewChunk; - else - { - pNewChunk->pNext = pFirst; - pFirst = pNewChunk; - } - - nLength += pNewChunk->nLength; - } - - void joinShare( MyType &rSrc ) - { - clear(); - - if( !rSrc.isFlat() ) - rSrc.flatten(); - - rSrc.initCount(); - pnRefs = rSrc.pnRefs; - (*pnRefs)++; - nLength = rSrc.nLength; - pFirst = rSrc.pFirst; - pLast = rSrc.pLast; - } - - void joinShare( const MyType &rSrc ) - { - clear(); - - rSrc.flatten(); - - if( !rSrc.isShared() ) - { - rSrc.pnRefs = new uint32_t; - (*rSrc.pnRefs) = 1; - } - pnRefs = rSrc.pnRefs; - (*pnRefs)++; - nLength = rSrc.nLength; - pFirst = rSrc.pFirst; - pLast = rSrc.pLast; - } - - /** - * This takes an object that was shared and makes a copy of the base data - * that was being shared so that this copy can be changed. This should be - * added before any call that will change this object; - */ - void unShare() const - { - if( isShared() == false ) - return; - - Chunk *pNew = newChunk( nLength ); - chr *pos = pNew->pData; - Chunk *i = pFirst; - for(;;) - { - cpy( pos, i->pData, i->nLength ); - pos += i->nLength; - i = i->pNext; - if( i == NULL ) - break; - } - decRefs(); - pLast = pFirst = pNew; - nLength = pNew->nLength; - } - - /** - * This decrements our ref count and pulls us out of the share. If the ref - * count hits zero because of this, it destroys the share. This is not - * safe to call on it's own, it's much better to call unShare. - */ - void decRefs() const - { - if( isShared() ) - { - (*pnRefs)--; - if( (*pnRefs) == 0 ) - destroyShare(); - else - { - pnRefs = NULL; - pFirst = NULL; - pLast = NULL; - nLength = 0; - } - } - } - - /** - * While the unShare function removes an instance from a share, this - * function destroys the data that was in the share, removing the share - * itself. This should only be called when the refcount for the share has - * or is about to reach zero. - */ - void destroyShare() const - { - delete pnRefs; - pnRefs = NULL; - realClear(); - } - -#ifdef VALTEST - void cpy( chr *dest, const chr *src, long count ) const - { - for( int j = 0; j < count; j++ ) - { - *dest = *src; - dest++; - src++; - } - } -#endif - - void initCount() const - { - if( !isShared() ) - { - pnRefs = new uint32_t; - (*pnRefs) = 1; - } - } - -private: - mutable long nLength; - mutable uint32_t *pnRefs; - mutable Chunk *pFirst; - mutable Chunk *pLast; - - mutable chralloc aChr; - mutable chunkalloc aChunk; -}; - -typedef FBasicString FString; - -#include "hash.h" -template<> uint32_t __calcHashCode( const FString &k ); -template<> bool __cmpHashKeys( const FString &a, const FString &b ); - - -#endif diff --git a/src/hash.cpp b/src/hash.cpp deleted file mode 100644 index c52e6b1..0000000 --- a/src/hash.cpp +++ /dev/null @@ -1,113 +0,0 @@ -#include "hash.h" - -subExceptionDef( HashException ) - -template<> uint32_t __calcHashCode( const int &k ) -{ - return k; -} - -template<> bool __cmpHashKeys( const int &a, const int &b ) -{ - return a == b; -} - -template<> uint32_t __calcHashCode( const unsigned int &k ) -{ - return k; -} - -template<> bool __cmpHashKeys( const unsigned int &a, const unsigned int &b ) -{ - return a == b; -} - -template<> -uint32_t __calcHashCode( const char * const &k ) -{ - if (k == NULL) - { - return 0; - } - - unsigned long int nPos = 0; - for( const char *s = k; *s; s++ ) - { - nPos = *s + (nPos << 6) + (nPos << 16) - nPos; - } - - return nPos; -} - -template<> bool __cmpHashKeys( const char * const &a, const char * const &b ) -{ - if( a == b ) - return true; - - for(int j=0; a[j] == b[j]; j++ ) - if( a[j] == '\0' ) - return true; - - return false; -} - -template<> -uint32_t __calcHashCode( char * const &k ) -{ - if (k == NULL) - { - return 0; - } - - unsigned long int nPos = 0; - for( const char *s = k; *s; s++ ) - { - nPos = *s + (nPos << 6) + (nPos << 16) - nPos; - } - - return nPos; -} - -template<> bool __cmpHashKeys( char * const &a, char * const &b ) -{ - if( a == b ) - return true; - - for(int j=0; a[j] == b[j]; j++ ) - if( a[j] == '\0' ) - return true; - - return false; -} - -template<> uint32_t __calcHashCode( const std::string &k ) -{ - std::string::size_type j, sz = k.size(); - const char *s = k.c_str(); - - unsigned long int nPos = 0; - for( j = 0; j < sz; j++, s++ ) - { - nPos = *s + (nPos << 6) + (nPos << 16) - nPos; - } - - return nPos; -} - -template<> bool __cmpHashKeys( const std::string &a, const std::string &b ) -{ - return a == b; -} - -template<> uint32_t __calcHashCode( const Hashable &k ) -{ - return 0; - //return k.getHashCode(); -} - -template<> bool __cmpHashKeys( const Hashable &a, const Hashable &b ) -{ - return false; - //return a.compareForHash( b ); -} - diff --git a/src/hash.h b/src/hash.h deleted file mode 100644 index e819379..0000000 --- a/src/hash.h +++ /dev/null @@ -1,744 +0,0 @@ -#ifndef HASH_H -#define HASH_H - -#include -#include -#include -#include -#include -#include "exceptionbase.h" -#include "hashable.h" -#include "serializable.h" -#include "serializer.h" - -#define bitsToBytes( n ) (n/32+(n%32>0 ? 1 : 0)) - -subExceptionDecl( HashException ) - -enum eHashException -{ - excodeNotFilled -}; - -template -uint32_t __calcHashCode( const T &k ); - -template -bool __cmpHashKeys( const T &a, const T &b ); - -struct __calcNextTSize_fast -{ - uint32_t operator()( uint32_t nCapacity, uint32_t nFill, uint32_t nDeleted ) const - { - if( nDeleted >= nCapacity/2 ) - return nCapacity; - return nCapacity*2+1; - } -}; - -template, typename valuealloc = std::allocator, typename challoc = std::allocator > -class Hash; - -template< typename key, typename _value, typename sizecalc = __calcNextTSize_fast, typename keyalloc = std::allocator, typename valuealloc = std::allocator<_value>, typename challoc = std::allocator > -struct HashProxy -{ - friend class Hash; -private: - HashProxy( Hash &h, key *k, uint32_t nPos, uint32_t hash ) : - hsh( h ), - pKey( k ), - nPos( nPos ), - hash( hash ), - bFilled( false ) - { - } - - HashProxy( Hash &h, uint32_t nPos, _value *pValue ) : - hsh( h ), - nPos( nPos ), - pValue( pValue ), - bFilled( true ) - { - } - - Hash &hsh; - key *pKey; - uint32_t nPos; - _value *pValue; - uint32_t hash; - bool bFilled; - -public: - operator _value &() - { - if( bFilled == false ) - throw HashException( - excodeNotFilled, - "No data assosiated with that key." - ); - return *pValue; - } - - _value &value() - { - if( bFilled == false ) - throw HashException( - excodeNotFilled, - "No data assosiated with that key." - ); - return *pValue; - } - - bool isFilled() - { - return bFilled; - } - - void erase() - { - if( bFilled ) - { - hsh._erase( nPos ); - hsh.onDelete(); - } - } - - _value operator=( _value nval ) - { - if( bFilled ) - { - hsh.va.destroy( pValue ); - hsh.va.construct( pValue, nval ); - hsh.onUpdate(); - } - else - { - hsh.fill( nPos, *pKey, nval, hash ); - hsh.onInsert(); - } - - return nval; - } - - _value *operator->() - { - if( bFilled == false ) - throw HashException( - excodeNotFilled, - "No data assosiated with that key." - ); - return pValue; - } -}; - -template -class Hash -{ - friend struct HashProxy; -public: - Hash() : - nCapacity( 11 ), - nFilled( 0 ), - nDeleted( 0 ), - bFilled( NULL ), - bDeleted( NULL ), - aKeys( NULL ), - aValues( NULL ), - aHashCodes( NULL ) - { - nKeysSize = bitsToBytes( nCapacity ); - bFilled = ca.allocate( nKeysSize ); - bDeleted = ca.allocate( nKeysSize ); - clearBits(); - - aHashCodes = ca.allocate( nCapacity ); - aKeys = ka.allocate( nCapacity ); - aValues = va.allocate( nCapacity ); - } - - Hash( const Hash &src ) : - nCapacity( src.nCapacity ), - nFilled( 0 ), - nDeleted( 0 ), - bFilled( NULL ), - bDeleted( NULL ), - aKeys( NULL ), - aValues( NULL ), - aHashCodes( NULL ) - { - nKeysSize = bitsToBytes( nCapacity ); - bFilled = ca.allocate( nKeysSize ); - bDeleted = ca.allocate( nKeysSize ); - clearBits(); - - aHashCodes = ca.allocate( nCapacity ); - aKeys = ka.allocate( nCapacity ); - aValues = va.allocate( nCapacity ); - - for( uint32_t j = 0; j < src.nCapacity; j++ ) - { - if( src.isFilled( j ) ) - { - insert( src.aKeys[j], src.aValues[j] ); - } - } - } - - Hash &operator=( const Hash &src ) - { - for( uint32_t j = 0; j < nCapacity; j++ ) - { - if( isFilled( j ) ) - if( !isDeleted( j ) ) - { - va.destroy( &aValues[j] ); - ka.destroy( &aKeys[j] ); - } - } - va.deallocate( aValues, nCapacity ); - ka.deallocate( aKeys, nCapacity ); - ca.deallocate( bFilled, nKeysSize ); - ca.deallocate( bDeleted, nKeysSize ); - ca.deallocate( aHashCodes, nCapacity ); - - nFilled = 0; - nDeleted = 0; - nCapacity = src.nCapacity; - nKeysSize = bitsToBytes( nCapacity ); - bFilled = ca.allocate( nKeysSize ); - bDeleted = ca.allocate( nKeysSize ); - clearBits(); - - aHashCodes = ca.allocate( nCapacity ); - aKeys = ka.allocate( nCapacity ); - aValues = va.allocate( nCapacity ); - - for( uint32_t j = 0; j < src.nCapacity; j++ ) - { - if( src.isFilled( j ) ) - { - insert( src.aKeys[j], src.aValues[j] ); - } - } - - return *this; - } - - virtual ~Hash() - { - for( uint32_t j = 0; j < nCapacity; j++ ) - { - if( isFilled( j ) ) - if( !isDeleted( j ) ) - { - va.destroy( &aValues[j] ); - ka.destroy( &aKeys[j] ); - } - } - va.deallocate( aValues, nCapacity ); - ka.deallocate( aKeys, nCapacity ); - ca.deallocate( bFilled, nKeysSize ); - ca.deallocate( bDeleted, nKeysSize ); - ca.deallocate( aHashCodes, nCapacity ); - } - - uint32_t getCapacity() - { - return nCapacity; - } - - uint32_t getFill() - { - return nFilled; - } - - uint32_t size() - { - return nFilled-nDeleted; - } - - uint32_t getDeleted() - { - return nDeleted; - } - - virtual HashProxy operator[]( key k ) - { - uint32_t hash = __calcHashCode( k ); - bool bFill; - uint32_t nPos = probe( hash, k, bFill ); - - if( bFill ) - { - return HashProxy( *this, nPos, &aValues[nPos] ); - } - else - { - return HashProxy( *this, &k, nPos, hash ); - } - } - - virtual void insert( key k, value v ) - { - uint32_t hash = __calcHashCode( k ); - bool bFill; - uint32_t nPos = probe( hash, k, bFill ); - - if( bFill ) - { - va.destroy( &aValues[nPos] ); - va.construct( &aValues[nPos], v ); - onUpdate(); - } - else - { - fill( nPos, k, v, hash ); - onInsert(); - } - } - - virtual void erase( key k ) - { - uint32_t hash = __calcHashCode( k ); - bool bFill; - uint32_t nPos = probe( hash, k, bFill ); - - if( bFill ) - { - _erase( nPos ); - onDelete(); - } - } - - struct iterator; - virtual void erase( struct iterator &i ) - { - if( this != &i.hsh ) - throw HashException("This iterator didn't come from this Hash."); - if( isFilled( i.nPos ) && !isDeleted( i.nPos ) ) - { - _erase( i.nPos ); - onDelete(); - } - } - - virtual void clear() - { - for( uint32_t j = 0; j < nCapacity; j++ ) - { - if( isFilled( j ) ) - if( !isDeleted( j ) ) - { - va.destroy( &aValues[j] ); - ka.destroy( &aKeys[j] ); - onDelete(); - } - } - - clearBits(); - } - - virtual value &get( key k ) - { - uint32_t hash = __calcHashCode( k ); - bool bFill; - uint32_t nPos = probe( hash, k, bFill ); - - if( bFill ) - { - return aValues[nPos]; - } - else - { - throw HashException( - excodeNotFilled, - "No data assosiated with that key." - ); - } - } - - virtual bool has( key k ) - { - bool bFill; - probe( __calcHashCode( k ), k, bFill, false ); - - return bFill; - } - - typedef struct iterator - { - friend class Hash; - private: - iterator( Hash &hsh ) : - hsh( hsh ), - nPos( 0 ), - bFinished( false ) - { - nPos = hsh.getFirstPos( bFinished ); - } - - iterator( Hash &hsh, bool bDone ) : - hsh( hsh ), - nPos( 0 ), - bFinished( bDone ) - { - } - - Hash &hsh; - uint32_t nPos; - bool bFinished; - - public: - iterator operator++( int ) - { - if( bFinished == false ) - nPos = hsh.getNextPos( nPos, bFinished ); - - return *this; - } - - iterator operator++() - { - if( bFinished == false ) - nPos = hsh.getNextPos( nPos, bFinished ); - - return *this; - } - - bool operator==( const iterator &oth ) - { - if( bFinished != oth.bFinished ) - return false; - if( bFinished == true ) - { - return true; - } - else - { - if( oth.nPos == nPos ) - return true; - return false; - } - } - - bool operator!=( const iterator &oth ) - { - return !(*this == oth ); - } - - iterator operator=( const iterator &oth ) - { - if( &hsh != &oth.hsh ) - throw HashException( - "Cannot mix iterators from different hash objects."); - nPos = oth.nPos; - bFinished = oth.bFinished; - } - - std::pair operator *() - { - return hsh.getAtPos( nPos ); - } - - key &getKey() - { - return hsh.getKeyAtPos( nPos ); - } - - value &getValue() - { - return hsh.getValueAtPos( nPos ); - } - }; - - iterator begin() - { - return iterator( *this ); - } - - iterator end() - { - return iterator( *this, true ); - } - - std::list getKeys() - { - std::list lKeys; - - for( uint32_t j = 0; j < nCapacity; j++ ) - { - if( isFilled( j ) ) - { - if( !isDeleted( j ) ) - { - lKeys.push_back( aKeys[j] ); - } - } - } - - return lKeys; - } - -protected: - virtual void onInsert() {} - virtual void onUpdate() {} - virtual void onDelete() {} - virtual void onReHash() {} - - virtual void clearBits() - { - for( uint32_t j = 0; j < nKeysSize; j++ ) - { - bFilled[j] = bDeleted[j] = 0; - } - } - - virtual void fill( uint32_t loc, key &k, value &v, uint32_t hash ) - { - bFilled[loc/32] |= (1<<(loc%32)); - va.construct( &aValues[loc], v ); - ka.construct( &aKeys[loc], k ); - aHashCodes[loc] = hash; - nFilled++; - //printf("Filled: %d, Deleted: %d, Capacity: %d\n", - // nFilled, nDeleted, nCapacity ); - } - - virtual void _erase( uint32_t loc ) - { - bDeleted[loc/32] |= (1<<(loc%32)); - va.destroy( &aValues[loc] ); - ka.destroy( &aKeys[loc] ); - nDeleted++; - //printf("Filled: %d, Deleted: %d, Capacity: %d\n", - // nFilled, nDeleted, nCapacity ); - } - - virtual std::pair getAtPos( uint32_t nPos ) - { - return std::pair(aKeys[nPos],aValues[nPos]); - } - - virtual key &getKeyAtPos( uint32_t nPos ) - { - return aKeys[nPos]; - } - - virtual value &getValueAtPos( uint32_t nPos ) - { - return aValues[nPos]; - } - - virtual uint32_t getFirstPos( bool &bFinished ) - { - for( uint32_t j = 0; j < nCapacity; j++ ) - { - if( isFilled( j ) ) - if( !isDeleted( j ) ) - return j; - } - - bFinished = true; - return 0; - } - - virtual uint32_t getNextPos( uint32_t nPos, bool &bFinished ) - { - for( uint32_t j = nPos+1; j < nCapacity; j++ ) - { - if( isFilled( j ) ) - if( !isDeleted( j ) ) - return j; - } - - bFinished = true; - return 0; - } - - uint32_t probe( uint32_t hash, key k, bool &bFill, bool rehash=true ) - { - uint32_t nCur = hash%nCapacity; - - // First we scan to see if the key is already there, abort if we - // run out of probing room, or we find a non-filled entry - for( int8_t j = 0; - isFilled( nCur ) && j < 32; - nCur = (nCur + (1< uint32_t __calcHashCode( const int &k ); -template<> bool __cmpHashKeys( const int &a, const int &b ); - -template<> uint32_t __calcHashCode( const unsigned int &k ); -template<> bool __cmpHashKeys( const unsigned int &a, const unsigned int &b ); - -template<> uint32_t __calcHashCode( const char * const &k ); -template<> bool __cmpHashKeys( const char * const &a, const char * const &b ); - -template<> uint32_t __calcHashCode( char * const &k ); -template<> bool __cmpHashKeys( char * const &a, char * const &b ); - -template<> uint32_t __calcHashCode( const std::string &k ); -template<> bool __cmpHashKeys( const std::string &a, const std::string &b ); - -template<> uint32_t __calcHashCode( const Hashable &k ); -template<> bool __cmpHashKeys( const Hashable &a, const Hashable &b ); - -template -Serializer &operator<<( Serializer &ar, Hash &h ) -{ - ar << h.size(); - for( typename Hash::iterator i = h.begin(); i != h.end(); i++ ) - { - std::pair p = *i; - ar << p.first << p.second; - } - - return ar; -} - -template -Serializer &operator>>( Serializer &ar, Hash &h ) -{ - h.clear(); - uint32_t nSize; - ar >> nSize; - - for( uint32_t j = 0; j < nSize; j++ ) - { - key k; value v; - ar >> k >> v; - h.insert( k, v ); - } - - return ar; -} - -template -Serializer &operator&&( Serializer &ar, Hash &h ) -{ - if( ar.isLoading() ) - { - return ar >> h; - } - else - { - return ar << h; - } -} - -#endif diff --git a/src/hashable.cpp b/src/hashable.cpp deleted file mode 100644 index 8565956..0000000 --- a/src/hashable.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "hashable.h" diff --git a/src/hashable.h b/src/hashable.h deleted file mode 100644 index 98643d5..0000000 --- a/src/hashable.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef HASHABLE_H -#define HASHABLE_H - -class Hashable -{ -public: - virtual ~Hashable() {}; - virtual unsigned long int getHashCode() = 0; - virtual bool compareForHash( Hashable &other ) = 0; -}; - -#endif diff --git a/src/hashfunction.cpp b/src/hashfunction.cpp deleted file mode 100644 index 51f2259..0000000 --- a/src/hashfunction.cpp +++ /dev/null @@ -1,10 +0,0 @@ -#include "hashfunction.h" - -HashFunction::HashFunction() -{ -} - -HashFunction::~HashFunction() -{ -} - diff --git a/src/hashfunction.h b/src/hashfunction.h deleted file mode 100644 index cbcf70f..0000000 --- a/src/hashfunction.h +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef HASH_FUNCTION -#define HASH_FUNCTION - -/** This represents the shell of a hash function. It must be aggregated in - * order to be used. Please read about it's two functions for specificatins - * relating to what values will be passed to them and what they should return - * for creating your own hash functions. - *@author Mike Buland. - */ -class HashFunction -{ -public: - /** - * Standard Constructor. - */ - HashFunction(); - - /** - * Standard Deconstructor. - */ - virtual ~HashFunction(); - - /** Hashes the value represnted by id. This must return a fairly unique - * number in the range of 0-2^32 (or whatever the size of an unsigned long - * is on your system) based on the id given. The faster the number changes - * the better in a general sence. The return value will be the index - * (after probing takes place) to the data assosiated with an id, so this - * function should always produce the same number for any given id. - *@param id The identifier to use to create a unique numerical identifier. - *@returns A mostly unique numerical identifier generated using the given - * id. - */ - virtual unsigned long int hash( const void *id ) = 0; - - /** This function must compare two ids in the format that this hashfunction - * accepts. For example, if the hash function hashes strings it should - * probably { return strcmp( id1, id2 ) == 0 }. - *@param id1 One value to use in the comparison - *@param id2 Another value to use in the comparison - *@returns True if the two values match, otherwise false. - */ - virtual bool cmpIDs( const void *id1, const void *id2 ) = 0; - -// virtual void *createPersistantID( const void *id ) = 0; -// virtual void destroyPersistantID( const void *id ) = 0; -}; - -#endif diff --git a/src/hashfunctioncasestring.cpp b/src/hashfunctioncasestring.cpp deleted file mode 100644 index 6361f45..0000000 --- a/src/hashfunctioncasestring.cpp +++ /dev/null @@ -1,39 +0,0 @@ -#include -#include -#include -#include "hashfunctioncasestring.h" - -HashFunctionCaseString::HashFunctionCaseString() -{ -} - -HashFunctionCaseString::~HashFunctionCaseString() -{ -} - -unsigned long int HashFunctionCaseString::hash( const void *id ) -{ - const char *str = (const char *)id; - unsigned long int nPos = 0; - for( int j = 0; str[j] != '\0'; j++ ) - { - nPos = tolower(str[j]) + (nPos << 6) + (nPos << 16) - nPos; -// nPos += nPos<<16|(((unsigned long int)tolower(str[j]))<<((j*7)%24)); - } - return nPos; -} - -bool HashFunctionCaseString::cmpIDs( const void *id1, const void *id2 ) -{ - const char *str1 = (const char *)id1; - const char *str2 = (const char *)id2; - - int j; - for( j = 0; str1[j] != '\0' && str2[j] != '\0'; j++ ) - { - if( tolower(str1[j]) != tolower(str2[j]) ) - return false; - } - return (str1[j]==str2[j]); -} - diff --git a/src/hashfunctioncasestring.h b/src/hashfunctioncasestring.h deleted file mode 100644 index 7816a1b..0000000 --- a/src/hashfunctioncasestring.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef HASH_FUNCTION_CASE_STRING -#define HASH_FUNCTION_CASE_STRING - -#include "hashfunction.h" - -/** A hash function for string data. This hash function does strings, but is - * actually generalized to handle any binary stream of characters terminated - * by a null character. This is different than HashFunctionString in that - * this does comparisons without regaurd to case. - *@author Mike Buland. - */ -class HashFunctionCaseString : public HashFunction -{ -public: - /** - * Standard Constructor. - */ - HashFunctionCaseString(); - - /** - * Standard Deconstructor. - */ - virtual ~HashFunctionCaseString(); - unsigned long int hash( const void *id ); - bool cmpIDs( const void *id1, const void *id2 ); -}; - -#endif diff --git a/src/hashfunctionint.cpp b/src/hashfunctionint.cpp deleted file mode 100644 index 4bd0feb..0000000 --- a/src/hashfunctionint.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include "hashfunctionint.h" - -HashFunctionInt::HashFunctionInt() -{ -} - -HashFunctionInt::~HashFunctionInt() -{ -} - -unsigned long int HashFunctionInt::hash( const void *id ) -{ - return (unsigned long)(id); -} - -bool HashFunctionInt::cmpIDs( const void *id1, const void *id2 ) -{ - return (unsigned long)(id1) == (unsigned long)(id2); -} - diff --git a/src/hashfunctionint.h b/src/hashfunctionint.h deleted file mode 100644 index 0fbc764..0000000 --- a/src/hashfunctionint.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef HASH_FUNCTION_INT -#define HASH_FUNCTION_INT - -#include "hashfunction.h" - -/** A hash function for integer data. Really, this does almost nothing except - * ensure we're dealing with positive indicies. - *@author Mike Buland. - */ -class HashFunctionInt : public HashFunction -{ -public: - /** - * Standard Constructor. - */ - HashFunctionInt(); - - /** - * Standard Deconstructor. - */ - virtual ~HashFunctionInt(); - unsigned long int hash( const void *id ); - bool cmpIDs( const void *id1, const void *id2 ); -}; - -#endif diff --git a/src/hashfunctionstring.cpp b/src/hashfunctionstring.cpp deleted file mode 100644 index bd14643..0000000 --- a/src/hashfunctionstring.cpp +++ /dev/null @@ -1,51 +0,0 @@ -#include "hashfunctionstring.h" -#ifndef NULL -#define NULL ((void *) 0) -#endif - -HashFunctionString::HashFunctionString() -{ -} - -HashFunctionString::~HashFunctionString() -{ -} - -unsigned long int HashFunctionString::hash( const void *id ) -{ - if (id == NULL) - { - return 0; - } - - unsigned long int nPos = 0; - for( const char *s = (const char *)id; *s; s++ ) - { - nPos = *s + (nPos << 6) + (nPos << 16) - nPos; - } - return nPos; -} - -bool HashFunctionString::cmpIDs( const void *id1, const void *id2 ) -{ - if (id1 == NULL || id2 == NULL) - { - return false; - } - if (id1 == id2) - { - return true; - } - - const char *str1 = (const char *)id1; - const char *str2 = (const char *)id2; - - int j; - for( j = 0; str1[j] != '\0' && str2[j] != '\0'; j++ ) - { - if( str1[j] != str2[j] ) - return false; - } - return (str1[j]==str2[j]); -} - diff --git a/src/hashfunctionstring.h b/src/hashfunctionstring.h deleted file mode 100644 index 7d2a1a6..0000000 --- a/src/hashfunctionstring.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef HASH_FUNCTION_STRING -#define HASH_FUNCTION_STRING - -#include "hashfunction.h" - -/** A hash function for string data. This hash function does strings, but is - * actually generalized to handle any binary stream of characters terminated - * by a null character. - *@author Mike Buland. - */ -class HashFunctionString : public HashFunction -{ -public: - /** - * Standard Constructor. - */ - HashFunctionString(); - - /** - * Standard Deconstructor. - */ - virtual ~HashFunctionString(); - unsigned long int hash( const void *id ); - bool cmpIDs( const void *id1, const void *id2 ); -}; - -#endif diff --git a/src/hashtable.cpp b/src/hashtable.cpp deleted file mode 100644 index dbcd964..0000000 --- a/src/hashtable.cpp +++ /dev/null @@ -1,424 +0,0 @@ -#include -#include -#include - -#include "hashtable.h" - -HashTable::HashTable( HashFunction *hNewFunc, unsigned long int nInitSize, bool bAllowDupes ) -{ - hFunc = hNewFunc; - nTableSize = nextPrime( nInitSize ); - aTable = new HashNode[nTableSize]; - //for( int j = 0; j < nTableSize; j++ ) if( aTable[j].id || aTable[j].data || aTable[j].bDeleted ) printf("Unclean entry\n"); - nSize = 0; - nFilled = 0; - this->bAllowDupes = bAllowDupes; -} - -HashTable::~HashTable() -{ - delete[] aTable; - delete hFunc; -} - -void HashTable::set( int j, const void *newID, const void *newData ) -{ - if( newData == NULL ) - { - printf("Inserting NULL data is indestinguishable from uninserted data!\n"); - } - aTable[j].id = newID; - aTable[j].data = newData; -} - -void HashTable::clear() -{ - memset( aTable, 0, sizeof(HashNode) * nTableSize ); -} - -bool HashTable::isFilled( int j ) -{ - return (aTable[j].id != NULL)||(aTable[j].bDeleted); -} - -void HashTable::reHash( unsigned long int nNewSize ) -{ - HashNode *aOldTable = aTable; - unsigned long int oldSize = nTableSize; - - // If the table can still be used if we just get rid of deleted items, don't - // change the size of the table, otherwise, go ahead and use the number - // passed in. - if( nSize > nTableSize>>1 ) - { - nTableSize = nextPrime( nNewSize ); - } - - aTable = newTable( nTableSize ); - //for( int j = 0; j < nTableSize; j++ ) if( aTable[j].id || aTable[j].data || aTable[j].bDeleted ) printf("Unclean entry\n"); - - nSize = 0; - nFilled = 0; - - for( unsigned long int j = 0; j < oldSize; j++ ) - { - if( aOldTable[j].id != NULL && aOldTable[j].bDeleted == false ) - { - insert( aOldTable[j].id, aOldTable[j].data ); - } - } - - delete[] aOldTable; -} - -unsigned long int HashTable::probe( unsigned long int nStart, const void *id ) -{ - int nHash = nStart; - nStart = nStart%nTableSize; - if( bAllowDupes == true ) - { - for( - unsigned long int j=0; - isFilled( nStart ) && j < 32; - nStart = (nStart+(1<cmpIDs( aTable[nStart].id, id ) == true && - aTable[nStart].bDeleted == false ) - { - return nStart; - } - } - } - } - // This is our insurance, if the table is full, then go ahead and rehash, - // then try again. - if( isFilled( nStart ) ) - { - reHash( getCapacity()*2 ); - return probe( nHash, id ); - } - return nStart; -} - -HashTable::HashNode *HashTable::newTable( unsigned long int nNewSize ) -{ - return new HashNode[nNewSize]; -} - -#ifdef HASH_DEBUG_VIS -void HashTable::printDebugLine( const char *exData ) -{ - char *buf = new char[getCapacity()+3]; - int j; - buf[0] = '['; - for( j = 0; j < getCapacity(); j++ ) - { - buf[j+1] = (aTable[j].bDeleted)?('X'):((isFilled( j ))?('#'):('-')); - } - buf[j+1] = ']'; - buf[j+2] = '\0'; - printf("%s %s\n", buf, exData ); - delete[] buf; -} -#endif - -bool HashTable::insert( const void *id, const void *data ) -{ - unsigned long int nPos = probe( hFunc->hash( id ), id )%nTableSize; - - if( bAllowDupes == true ) - { - if( aTable[nPos].id == NULL && aTable[nPos].bDeleted == false ) - { - set( nPos, id, data ); -#ifdef HASH_DEBUG_VIS - printDebugLine( (const char *)id ); -#endif - nSize++; - nFilled++; - return true; - } - else - { - return false; - } - } - else - { - if( aTable[nPos].id == NULL && aTable[nPos].bDeleted == false ) - { - set( nPos, id, data ); -#ifdef HASH_DEBUG_VIS - printDebugLine( (const char *)id ); -#endif - nSize++; - nFilled++; - return true; - } - else if( hFunc->cmpIDs( aTable[nPos].id, id ) == true ) - { - set( nPos, id, data ); -#ifdef HASH_DEBUG_VIS - printDebugLine( (const char *)id ); -#endif - return true; - } - else - { - return false; - } - } -} - -const void *HashTable::get( const void *id, unsigned long int nSkip ) -{ - unsigned long int nPos = hFunc->hash( id )%nTableSize; - - for( unsigned long int j=0; j < 32; nPos = (nPos+(1<cmpIDs( id, aTable[nPos].id ) ) - { - if( nSkip == 0 ) - { - return aTable[nPos].data; - } - else - { - nSkip--; - } - } - } - } - - if( bAllowDupes ) - { - unsigned long int nOldPos = nPos; - for( nPos++; nPos != nOldPos; nPos=(nPos+1)%nTableSize ) - { - if( !isFilled( nPos ) ) return NULL; - if( aTable[nPos].bDeleted == false ) - { - if( hFunc->cmpIDs( id, aTable[nPos].id ) ) - { - if( nSkip == 0 ) - { - return aTable[nPos].data; - } - else - { - nSkip--; - } - } - } - } - } - - return NULL; -} - -const void *HashTable::getKey( const void *id, unsigned long int nSkip ) -{ - unsigned long int nPos = hFunc->hash( id )%nTableSize; - - for( unsigned long int j=0; j < 32; nPos = (nPos+(1<cmpIDs( id, aTable[nPos].id ) ) - { - if( nSkip == 0 ) - { - return aTable[nPos].id; - } - else - { - nSkip--; - } - } - } - } - - if( bAllowDupes ) - { - unsigned long int nOldPos = nPos; - for( nPos++; nPos != nOldPos; nPos=(nPos+1)%nTableSize ) - { - if( !isFilled( nPos ) ) return NULL; - if( aTable[nPos].bDeleted == false ) - { - if( hFunc->cmpIDs( id, aTable[nPos].id ) ) - { - if( nSkip == 0 ) - { - return aTable[nPos].id; - } - else - { - nSkip--; - } - } - } - } - } - - return NULL; -} - -void *HashTable::getFirstItemPos() -{ - HashPos *pos = new HashPos; - return pos; -} - -const void *HashTable::getItemData( void *xPos ) -{ - return aTable[((HashPos *)xPos)->nPos].data; -} - -const void *HashTable::getItemID( void *xPos ) -{ - return aTable[((HashPos *)xPos)->nPos].id; -} - -void *HashTable::getNextItemPos( void *xPos ) -{ - HashPos *pos = (HashPos *)xPos; - if( pos->bStarted == false ) - { - pos->bStarted = true; - pos->nPos = 0; - } - else - { - pos->nPos++; - } - if( pos->nPos < nTableSize ) - { - for( ; pos->nPos < nTableSize; pos->nPos++ ) - { - if( isFilled( pos->nPos ) && - aTable[pos->nPos].bDeleted == false ) - { - return xPos; - } - } - } - - delete pos; - - return NULL; -} - -// Big-O sqrt(n) -// Change this to be erethpothynies table with a storage -// lookup later on. -bool HashTable::isPrime (int num) -{ - if (num == 2) // the only even prime - return true; - else if (num % 2 == 0) // other even numbers are composite - return false; - else - { - //bool prime = true; - int divisor = 3; - int upperLimit = static_cast(sqrt(num) + 1); - while (divisor <= upperLimit) - { - if (num % divisor == 0) - return false; - // prime = false; - divisor +=2; - } - return true; - } -} - -// Big-O n^(3/2) -int HashTable::nextPrime( int base ) -{ - int nPrime; - for( nPrime = base; isPrime( nPrime ) == false; nPrime++ ); - return nPrime; -} - -unsigned long int HashTable::getCapacity() -{ - return nTableSize; -} - -unsigned long int HashTable::getSize() -{ - return nSize; -} - -double HashTable::getLoad() -{ - return (double)(nFilled)/(double)(nTableSize); -} - -const void *HashTable::operator[](const void *id) -{ - return get( id ); -} - -bool HashTable::del( const void *id, int nSkip ) -{ - unsigned long int nPos = hFunc->hash( id )%nTableSize; - - for( unsigned long int j=0; j < 32; nPos = (nPos+(1<cmpIDs( id, aTable[nPos].id ) && - aTable[nPos].bDeleted == false ) - { - if( nSkip == 0 ) - { - aTable[nPos].bDeleted = true; - nSize--; -#ifdef HASH_DEBUG_VIS - printDebugLine( (const char *)id ); -#endif - return true; - } - else - { - nSkip--; - } - } - } - - return false; -} - diff --git a/src/hashtable.h b/src/hashtable.h deleted file mode 100644 index 179b694..0000000 --- a/src/hashtable.h +++ /dev/null @@ -1,308 +0,0 @@ -/**\hashtable.h - * Describes the HashFunction, HashFunctionString, and HashTable classes. It - * was just easier to put them all in one set of files. - *@author Mike Buland - */ - -#ifndef HASH_TABLE_H -#define HASH_TABLE_H - -//Uncomment this line to see a cool text-mode visualization of what's going on -//#define HASH_DEBUG_VIS 1 - -#include -#include -#include - -#include "hashfunction.h" - -/** - * A simple yet flexable hash-table. This uses several tricks to help ensure - * that the table is always running at maximum efficiency. You no longer have - * to specify a "danger fill level" when more space is needed a rehash is - * automatically trigered. Deleting elements is fully supported, as well as - * duplicate elements. To work with and allow duplicates simple construct your - * HashTable the way you normally would, but when deleting or getting elements - * you can specify a skip value. This effectively allows you to treat elements - * with duplicate ID's as though they were in a zero-based array. The first - * element inserted with a given ID would be at skip zero, the next at skip 1 - * and so on. This allows you to quickly search for elements with duplicate - * names, just stop when you get a null for a skip number, i.e. - *
- *   for( int j = 0;; j++ )
- *   {
- *       void *pData = hash.get( myID, j );
- *       if( !pData ) break;
- *       // Do something interesting with pData
- *   }
- * 
- * There are new features in this HashTable that also allow for memory saving - * when dealing with systems where many elements are being deleted from the - * table. In those cases the elements deleted cannot be simply deleted, instead - * they have to be marked as deleted and hidden from the user, but maintained in - * the table so that future hashing operations don't fail. When rehashing - * occurs all elements marked as deleted are quietly removed. In these cases, - * if the number of deleted items would free enough space in the table for the - * table to be used efficiently without resizing, it is left the same size and - * rehashing is performed effectively in place, allowing the deleted items to - * be removed. - *
- * For info on adding new hashing algorithms, please see the HashFunction class. - *@author Mike Buland - *@todo Fix probing for tables that allow duplicates, and delete an item, then - * insert an item with the same name. - */ -class HashTable -{ -public: - /** Constructs a hash table. - *@param hNewFunc A pointer to a hashfunction class to use. If this is - * null the default general string type will be used. - *@param nInitSize The initial size of the hashtable. - *@param bAllowDupes Setting this value to true allows the system to - * insert more than one copy of any given key. This can be tricky, and - * will require you to use the nSkip parameter on the get function. - */ - HashTable( HashFunction *hNewFunc, unsigned long int nInitSize, bool bAllowDupes=false ); - - /** - * Destroys the hashtable, cleaning up all internal storage, but not stored - * elements. Also deletes the HashFunction passed in in the constructor. - */ - virtual ~HashTable(); - - /** Inserts an item into the hashtable. This function will trigger a - * rehash if adding another item would force the table's load factor over - * the danger level. - *@param id used to find the data later. - *@param data The data item to insert into the table with the identifier - * id - *@returns True if insertion was successfull, and false if it failed. - */ - bool insert( const void *id, const void *data ); - - /** Gets an item in the hashtable based on the id of that item. If there - * is more than one item with the same id you can use the nSkip parameter - * to access all of them. - *@param id The id of the item you're trying to find. - *@param nSkip The number of items with that id to skip before returning - * with the requested item. - *@returns A pointer to the data stored at the given id. - */ - const void *get( const void *id, unsigned long int nSkip=0 ); - - const void *getKey( const void *id, unsigned long int nSkip=0 ); - - /** Gets the total capacity of the hashtable. This is actually the number - * of total positions available inside the hashtable at the moment. This - * will change when the hashtable's load exceeds the danger level. - * Please note that this is NOT the actual amount of space available. - * In reality you can only access about 45-50 percent of that space. - *@returns The total capacity. - */ - unsigned long int getCapacity(); - - /** Gets the number of filled in items in the hash table. This is roughly - * equivelent to the getSize function assosiated with the Lists. - *@returns The number of filled in items in the hash table. - */ - unsigned long int getSize(); - - /** Gets the load (percentage) of filled in items in the table. This is - * technically the size divided by the capacity, but is definately usefull - * since it's required to check if it's time to rehash. - *@returns The table load in the range 0.0 to 1.0 - */ - double getLoad(); - - /** Sets up an xPos object for use indexing the items in the table. Call - * this first and follow the directions for getNextItemPos below to - * iterate through every item in the table, while avoiding the empty - * spaces. - *@returns A pointer to a xPos object telling the hashtable where to find - * the item you're looking at. - */ - void *getFirstItemPos(); - - /** Get the item's data that is being pointed to by xPos. This is only - * valid after xPos was created using getFirstItemPos and getNextItemPos - * was called at least once. - *@param xPos supplied by getFirstItemPos. - *@returns The key value that was used to insert the data into the table. - */ - const void *getItemData( void *xPos ); - - /** Get the item's ID that is being pointed to by xPos. This is only - * valid after xPos was created using getFirstItemPos and getNextItemPos - * was called at least once. - *@param xPos supplied by getFirstItemPos. - *@returns The key value that was used to insert the data into the table. - */ - const void *getItemID( void *xPos ); - - /** Used for iterating through a hash table sequentially. This will - * update the xPos pointer to point to the next time, all ready to - * be accessed with getItemID and getItemData. This must be called at - * least once before xPos is meaningful, and will return a NULL when it - * has reached the last item. - *@param xPos This must be an object created by a call to the function - * getFirstItemPos, and is only meaningful to the internal routines. - * Aborting a call in the middle (not running to the end of the table) - * may result in a memory leak at the moment. - *@returns xPos if still iterating through the list, otherwise it will - * return NULL when the end has been reached and the xPos variable has - * been deleted. - */ - void *getNextItemPos( void *xPos ); - - /** A helpful operator to make accessing items easier. Please note that - * this simply returns a pointer to the data stored internally, and cannot - * be used like the STL operator to store new data, use insert for that. - *@param id The identifier used to store the requested item. - *@returns The data value assosiated with the given id, or NULL if it - * wasn't found in the table. - */ - const void *operator[](const void *id); - - /** - * Delete the specified item from the hashtable. This actually keeps the - * data and marks it deleted. For all intents and purposes to the user it - * is deleted, except that the space is still used until a rehash is forced. - * This means that in hashtables where elements are being inserted and - * deleted frequently you may run into a higher rate of expansion. - *@param id The ID to delete. - *@param nSkip The number of similar id's to skip before deleting in a - * hashtable that allows duplicates. - *@returns True if the element was found and deleted, false otherwise. - */ - bool del( const void *id, int nSkip=0 ); - - /** - * Deletes every entry in the hash table. See the notes on del to see what - * this means, except that since no data is being kept, the entire table is - * just marked as usable space. - */ - void clear(); - -private: - /** - * Contains info related to a position in the hashtable. Used for - * searching through hashtables one item at a time, in order. This class - * should never be created by anything but a HashTable, and should never - * be referenced directly. Instead the hashtable returns a void pointer, - * which is what should be passed back in next time you use a search - * function. Always finish a search, since the object is deleted at the - * end of the search. - *@author Mike Buland - */ - class HashPos - { - public: - /** Create a blank HashPos. */ - HashPos() { bStarted=false; nPos = 0; }; - /** Has the search been started? */ - bool bStarted; - /** The position (index) into the backend storage structure. */ - unsigned long int nPos; - }; - - /** - * All data related to a single element in the hashtable. This should - * really only be used and manipulated by the HashTable itself. - *@author Mike Buland - */ - typedef struct HashNode - { - public: - /** Create a new, empty HashNode. */ - HashNode() { id = NULL; data = NULL; bDeleted = false; }; - /** A pointer to the original ID that was used to key the data. */ - const void *id; - /** A pointer to the data stored along with the above ID. */ - const void *data; - /** Weather or not this data should really...exist */ - bool bDeleted; - } HashNode; - -private: - /** - * Just sets the values in the element to some friendly values. - *@param newID The new ID to store. - *@param newData The new Data to store. - */ - void set( int j, const void *newID, const void *newData ); - /** - * Tells you if the node is filled or not. - *@returns True=an ID has been stored here, False=no ID. - */ - bool isFilled( int j ); - /** - * This actually resizes, but since every resize requires a reHash to go - * along with it, that's the name. This actually creates a new buffer for - * all of the contained data and then pulls every old element that was in - * the old table out and performs the hashing placement calculations again. - * This function skips all data that was marked as deleted, so at this - * point it really will be. - *@param nNewSize The new size to set the table to while re-hashing. - *@returns True if the operation was successful, false otherwise. - */ - void reHash( unsigned long int nNewSize ); - - /** - * Helper function to allocate a new table. Really just does the memory - * allocation. - *@param nNewSize The size of the table to generate. - *@returns A new, blank array of HashNode objects the size you specified. - */ - HashNode *newTable( unsigned long int nNewSize ); - - /** - * This function is used once an actual hash code is obtained. nStart is - * the given hash code, which is then wrapped to the size of the table. If - * there is data at that location, tests are performed to see if it's the - * right one. If it is, then it is returned, otherwise a series of further - * tests based on a 2^n search pattern is performed. The position of the - * requested data in the back-end storage is returned if found, otherwise - * another less useful value is returned... - *@param nStart The initial hashcode of the ID testing for. - *@param id A pointer to the id that is being searched for. - *@returns The real location of the data requested. - */ - unsigned long int probe( unsigned long int nStart, const void *id ); - - /** - * Simple helper function to determine if a number is prime or not. - * This function runs in sqrt(n) time. - *@param num Number to test for prime-hood. - *@returns True if the number is prime, false otherwise. - */ - bool isPrime( int num ); - - /** - * Given any number, this function finds the first number after it that is - * prime. Since this number is a multiple internally it's rare that the - * starting number would be prime. - *@param base The number to start the prime search on. - *@returns The first prime after the number given. - */ - int nextPrime( int base ); - -#ifdef HASH_DEBUG_VIS - void printDebugLine( const char *exData ); -#endif - - /** A pointer to the HashFunction subclass instance to use. */ - HashFunction *hFunc; - /** The complete array of HashNode objects to store data in. */ - HashNode *aTable; - /** The actual size of the table, not how many elements are in it. */ - unsigned long int nTableSize; - /** The number of elements that are in the table. */ - unsigned long int nSize; - /** The number of elements that are unavailable now. */ - unsigned long int nFilled; - /** Allow duplicate ID's in the table. */ - bool bAllowDupes; -}; - -#endif diff --git a/src/http.cpp b/src/http.cpp deleted file mode 100644 index df7dafe..0000000 --- a/src/http.cpp +++ /dev/null @@ -1,377 +0,0 @@ -#include -#include -#include "http.h" -#include "hashfunctionstring.h" - -Http::Http( Connection *pConnection ) : hReqHeader( new HashFunctionString(), 100 ) -{ - pCon = pConnection; - nParseState = parseInit; -} - -Http::~Http() -{ - for( int j = 0; j < lStrings.getSize(); j++ ) - { - delete (std::string *)lStrings[j]; - } -} - -bool Http::parseRequest() -{ - for(;;) - { - pCon->readInput(); - switch( nParseState ) - { - case parseInit: - { - int nLen = pCon->scanInputFor( CR ); - if( nLen == -1 ) - { - return false; - } - else - { - nReqType = getRequestType( pCon->getInput() ); - pCon->usedInput( pCon->scanInputFor(' ')+1 ); - - nLen = pCon->scanInputFor(' '); - sReqURI.append( pCon->getInput(), nLen ); - pCon->usedInput( nLen+1 ); - - if( !strncmp( pCon->getInput(), "HTTP/", 5 ) ) - { - char mbuf[2]={'\0','\0'}; - unsigned char major, minor; - - pCon->usedInput( 5 ); - mbuf[0] = pCon->getInput()[0]; - major = (unsigned char)atoi(mbuf); - mbuf[0] = pCon->getInput()[2]; - minor = (unsigned char)atoi(mbuf); - setRequestVersion( major, minor ); - if( checkRequestVer() ) - { - nParseState = parseHeader; - } - else - { - setResponseStatus( statusHTTPVersionNotSupported ); - //printf("Verson not supported.\n"); - return true; - } - - pCon->usedInput( 5 ); - } - else - { - setResponseStatus( statusBadRequest ); - } - - //return false; - } - } - break; - - case parseHeader: - { - int nLen = pCon->scanInputFor( CR ); - //printf("nLen = %d: :::%s:::\n", nLen, pCon->getInput() ); - if( nLen == -1 ) - { - pCon->readInput( 1, 0); - } - else if( nLen == 0 ) - { - // We've got our double-newline, time for content. - pCon->usedInput( 2 ); - setResponseStatus( statusOK ); - return true; - } - else - { - nLen = pCon->scanInputFor(':'); - if( nLen == -1 ) - { - //printf("No colon? what are you trying to pull?\n"); - } - else - { - std::string *pName = new std::string( pCon->getInput(), nLen ); - lStrings.append( pName ); - pCon->usedInput( nLen+1 ); - - nLen = pCon->scanInputFor( CR ); - std::string *pValue = convSpaceString( pCon->getInput(), nLen ); - lStrings.append( pValue ); - pCon->usedInput( nLen+2 ); - - hReqHeader.insert( - pName->c_str(), - pValue->c_str() - ); - - //printf("::%s = \"%s\"\n", - // pName->c_str(), - // pValue->c_str() - // ); - } - } - } - break; - - case parseFinished: - break; - } - } -} - -bool Http::buildResponse( short nResponseCode, const char *sResponse ) -{ - if( nResponseCode > 0 ) - { - nResStatus = nResponseCode; - } - - if( sResponse == NULL ) - { - sResStatusStr = "uh yeah"; - } - else - { - sResStatusStr = sResponse; - } - - time_t curTime; - time( &curTime ); - gmtime_r( &curTime, &tResTime ); - - sServerStr = "libbu++ Http/0.0.1"; - bResPersistant = false; - - //char buf[30]; - //strftime( buf, 30, "%a, %d %b %Y %H:%M:%S GMT", &tResponseTime ); - - return true; -} - -bool Http::sendResponse() -{ - char buf[256]; - - sprintf( buf, "HTTP/1.1 %d %s\r\n", nResStatus, sResStatusStr.c_str() ); - pCon->appendOutput( buf ); - - strftime( buf, 256, "Date: %a, %d %b %Y %H:%M:%S GMT\r\n", &tResTime ); - pCon->appendOutput( buf ); - - sprintf( buf, "Server: %s\r\n", sServerStr.c_str() ); - pCon->appendOutput( buf ); - - if( bResPersistant ) - { - } - else - { - pCon->appendOutput("Connection: close\r\n"); - } - - sprintf( buf, "Content-Type: %s\r\n", sResMime.c_str() ); - pCon->appendOutput( buf ); - - sprintf( buf, "Content-Length: %d\r\n", sResContent.size() ); - pCon->appendOutput( buf ); - - pCon->appendOutput("\r\n"); - - pCon->appendOutput( sResContent.c_str(), sResContent.size() ); - - return true; -} - -void Http::setResponsePersistant( bool bPersistant ) -{ - bResPersistant = bPersistant; -} - -void Http::setResponseContent( const char *sMime, const char *sContent, int nLen ) -{ - sResMime = sMime; - sResContent.erase(); - sResContent.append( sContent, nLen ); -} - -std::string *Http::convSpaceString( const char *sStr, int nLen ) -{ - int nNewLen = 0; - bool bStart = true; - bool bSpace = false; - - for( int j = 0; j < nLen; j++ ) - { - if( sStr[j] == ' ' || sStr[j] == '\t' ) - { - if( bStart ) - { - } - else if( bSpace == false ) - { - bSpace = true; - nNewLen++; - } - } - else - { - bStart = false; - bSpace = false; - nNewLen++; - } - } - if( bSpace ) - { - nNewLen--; - } - - std::string *pSStr = new std::string; - //char *pStr = pSStr->c_str(); - nNewLen = 0; - bStart = true; - bSpace = false; - - for( int j = 0; j < nLen; j++ ) - { - if( sStr[j] == ' ' || sStr[j] == '\t' ) - { - if( bStart ) - { - } - else if( bSpace == false ) - { - bSpace = true; - *pSStr += ' '; - //pStr[nNewLen++] = ' '; - } - } - else - { - bStart = false; - bSpace = false; - *pSStr += sStr[j]; - //pStr[nNewLen++] = sStr[j]; - } - } - if( bSpace == true ) - { - nNewLen--; -// pStr[nNewLen] = '\0'; - } - - return pSStr; -} - -const char *Http::getRequestURI() -{ - return sReqURI.c_str(); -} - -short Http::getRequestType( const char *sType ) -{ - if( !strncmp( sType, "OPTIONS", 7 ) ) - { - return reqOptions; - } - else if( !strncmp( sType, "GET", 3 ) ) - { - return reqGet; - } - else if( !strncmp( sType, "HEAD", 4 ) ) - { - return reqHead; - } - else if( !strncmp( sType, "POST", 4 ) ) - { - return reqPost; - } - else if( !strncmp( sType, "PUT", 3 ) ) - { - return reqPut; - } - else if( !strncmp( sType, "DELETE", 6 ) ) - { - return reqDelete; - } - else if( !strncmp( sType, "TRACE", 5 ) ) - { - return reqTrace; - } - else if( !strncmp( sType, "CONNECT", 7 ) ) - { - return reqConnect; - } - else - { - printf(" Uh oh, extension!\n"); - return reqExtension; - } -} - -const char *Http::getRequestType( short nType ) -{ - switch( nType ) - { - case reqOptions: return "OPTIONS"; - case reqGet: return "GET"; - case reqHead: return "HEAD"; - case reqPost: return "POST"; - case reqPut: return "PUT"; - case reqDelete: return "DELETE"; - case reqTrace: return "TRACE"; - case reqConnect: return "CONNECT"; - case reqExtension: return "EXTENSION"; - default: return "INVALID VALUE"; - } -} - -short Http::getRequestType() -{ - return nReqType; -} - -const char *Http::getRequestTypeStr() -{ - return getRequestType( nReqType ); -} - -void Http::setResponseStatus( short nStatus ) -{ - nResStatus = nStatus; -} - -void Http::setRequestVersion( unsigned char nMajor, unsigned char nMinor ) -{ - cReqVersion = (nMajor<<4)|nMinor; -} - -unsigned char Http::getRequestMinorVer() -{ - return cReqVersion&0x0F; -} - -unsigned char Http::getRequestMajorVer() -{ - return cReqVersion>>4; -} - -bool Http::checkRequestVer() -{ - if( cReqVersion == HTTP11 ) - return true; - return false; -} - -const char *Http::getHeader( const char *lpStr ) -{ - return (const char *)hReqHeader[lpStr]; -} - diff --git a/src/http.h b/src/http.h deleted file mode 100644 index 7e9f9a0..0000000 --- a/src/http.h +++ /dev/null @@ -1,273 +0,0 @@ -/**\file http.h - * Describe a Hyper Text Transfer Protocol processor. This class will allow - * any program to act as either an HTTP server, client, or both. It contains - * a number of additional helpers and subclasses. - *@author Mike Buland - */ - -#ifndef HTTP_H -#define HTTP_H - -#include -#include "connection.h" -#include "linkedlist.h" -#include "hashtable.h" - -#define CR '\r' /**< The ASCII value of a Carrage Return */ -#define LF '\n' /**< The ASCII value of a Line Feed */ -#define CRLF CR LF /**< Combo of CR+LF for use in http */ - -/** - * Macro to create combined http version codes. This just makes processing a - * little bit faster for the most part. - *@param maj Major version number, between 0 and 15 - *@param min Minor version number, between 0 and 15 - *@returns A one byte combined version number suitable for use in switches. - */ -#define HTTPVER( maj, min ) ((maj<<4)|(min)) - -#define HTTP10 HTTPVER( 1, 0 ) /**< Combined version code for http 1.0 */ -#define HTTP11 HTTPVER( 1, 1 ) /**< Combined version code for http 1.1 */ - -/** - * This is the master HTTP processing class. One instance handles one - * transaction, in the future a different mechanism may be thought up, but for - * now this means that you must create multiple objects to handle a single - * connection that contains multiple requests. - * In the constructor the Http class is given a connection object. This object - * should already be initialized and connected to whatever socket it wants to - * be sending and receiving data to and from. Once that's done you can call - * parseRequest if you're acting as a server, or a variety of buildRequest - * functions to create and send a request if you're a client. - * Please note that this class does not provide any HTTP or extended format - * processing systems, but will allow for mime types tables to be registered. - *@author Mike Buland - */ -class Http -{ -public: - /** - * Create an Http object tied to an existing connection object. - *@param pConnection The live connection object to deal with. - */ - Http( Connection *pConnection ); - - /** - * Standard Deconstructor. - */ - virtual ~Http(); - - /** - * Perform all parsing needed to figure out what an HTTP client wants from - * us. This will setup a number of properties in the Http object itself - * and has the possibility of setting one or more response states initially. - * These states should be checked for immediately after parsing to see if - * an appropriate error message should be generated. These errors can - * include issues with protocol, data formats, or unknown versions of the - * protocol. - *@returns True means that all processing is finished, false means that - * the parseRequest function should be called again when more data is - * ready. A return value of true does not indicate success, only that - * processing is finished, the getResponseStatus function should be called - * to see what status was set in the parse routine. A 200 indicates that - * as far as the parser is concerned, everything when smoothly. Otherwise - * it's your responsibility to build the appropriate error response body - * (like an html file) and send it as the response. - */ - bool parseRequest(); - - /** - * Get a request type's internal Http object id based on the string - * representation. These can be any HTTP/1.1 standard request type. - *@param sType The string that should be checked for type. This is in all - * caps, just like if it came from the HTTP client, which is most often - * the case. - *@returns The numerical ID of the given request type. Please note that - * HTTP/1.1 standard specifies that any string is valid here as long as - * the non-basic string is a request type understood by the serving - * software. This means that anything that is non-standard will return - * a type reqExtension and not an error. This is not a mistake. - */ - short getRequestType( const char *sType ); - - /** - * Get the string representation of an Http object request type integer ID. - * This is used mainly for debugging to be sure the system has what we - * think it has. - *@param nType The integer ID of the request type to process. - *@returns The HTTP/1.1 string representation of that Http object ID code. - */ - const char *getRequestType( short nType ); - - /** - * Returns the Http object request type ID code that is stored in the - * object by either the parseRequest function or use of the buildRequest - * functions. - *@returns The ID of the request type stored in the object. - */ - short getRequestType(); - - /** - * Same as getRequestType, only returns the string representation. - *@returns The string representation of the request type ID stored in the - * object. - */ - const char *getRequestTypeStr(); - - /** - * Sets the version of the request used by the system. This will be used - * by parse request, but is also part of the buildRequest tool functions. - *@param nMajor The major version number. - *@param nMinor The minor version number. - */ - void setRequestVersion( unsigned char nMajor, unsigned char nMinor ); - - /** - * Gets the major version number of the protocol used/to be used in this - * request. - *@returns The major version number of the request protocol. - */ - unsigned char getRequestMinorVer(); - - /** - * Gets the minor version number of the protocol used/to be used in this - * request. - *@returns The minor version number of the request protocol. - */ - unsigned char getRequestMajorVer(); - - /** - * Checks the stored request version against an internal table of supported - * protocol versions. - *@returns True if the protocol version is supported, false otherwise. - */ - bool checkRequestVer(); - - /** - * Converts an arbitrary string to a new string object with space saving - * operations performed ala the HTTP/1.1 specs. All leading and trailing - * whitespace is stripped, and all whitespace within the string is reduced - * to a single space char. - *@param sStr A pointer to the string data to process. - *@param nLen The length of the string to process. Since this function is - * often called on stream data, there is no null terminator where we need - * one. This is here for convinience so the data doesn't need to be hacked - * up or moved to an intermediate buffer. - *@returns A new string that may well be shorter than the original but that - * will have the same value as far as the HTTP/1.1 specs are concerned. - */ - std::string *convSpaceString( const char *sStr, int nLen ); - - /** - * Gets a string pointer to the URI that was/is being requested. This can - * be any RFC standard URI, with or without protocol and domain. - *@returns A pointer to the URI that was/is being requested. - */ - const char *getRequestURI(); - - /** - * Set a new response status. This status can be anything that the HTTP - * specs allow. Other values are allowed as well, but beware, not all - * servers/clients will accept values that are not in the tables in this - * class. - *@param nStatus The status to set. - */ - void setResponseStatus( short nStatus ); - - bool buildResponse( short nResponseCode=-1, const char *sResponse=NULL ); - void setResponseContent( const char *sMime, const char *sContent, int nLen ); - void setResponsePersistant( bool bPersistant ); - bool sendResponse(); - - enum - { - reqOptions, - reqGet, - reqHead, - reqPost, - reqPut, - reqDelete, - reqTrace, - reqConnect, - reqExtension - }; - - enum - { - statusContinue = 100, - statusSwitchProto = 101, - - statusOK = 200, - statusCreated = 201, - statusAccepted = 202, - statusNonAuthInfo = 203, - statusNoContent = 204, - statusResetContent = 205, - statusPartialContent = 206, - - statusMultiChoices = 300, - statusMovedPermanently = 301, - statusFound = 302, - statusSeeOther = 303, - statusNotModified = 304, - statusUseProxy = 305, - statusUnused = 306, - statusTempRedirect = 307, - - statusBadRequest = 400, - statusUnauthorized = 401, - statusPaymentRequired = 402, - statusForbidden = 403, - statusNotFound = 404, - statusMethodNotAllowed = 405, - statusNotAcceptable = 406, - statusProxyAuthRequired = 407, - statusRequestTimeout = 408, - statusConflict = 409, - statusGone = 410, - statusLengthRequired = 411, - statusPreconditionFailed = 412, - statusRequestEntityTooLarge = 413, - statusRequestURITooLong = 414, - statusUnsupportedMediaType = 415, - statusRequestedRangeNotSatisfiable = 416, - statusExpectationFailed = 417, - - statusInternalServerError = 500, - statusNotImplemented = 501, - statusBadGateway = 502, - statusServiceUnavailable = 503, - statusGatewayTimeout = 504, - statusHTTPVersionNotSupported = 505 - }; - - const char *getHeader( const char *lpStr ); - -private: - Connection *pCon; - unsigned char nParseState; - - short nReqType; - std::string *pReqStr; - std::string sReqURI; - unsigned char cReqVersion; - HashTable hReqHeader; - LinkedList lStrings; - - std::string sServerStr; - std::string sResMime; - std::string sResContent; - std::string sResStatusStr; - bool bResPersistant; - struct tm tResTime; - short nResStatus; - - enum - { - parseInit, - parseHeader, - parseFinished - }; -}; - -#endif diff --git a/src/httpget.cpp b/src/httpget.cpp deleted file mode 100644 index ee1f29c..0000000 --- a/src/httpget.cpp +++ /dev/null @@ -1,263 +0,0 @@ -#include "httpget.h" -#include "exceptions.h" -#include "connection.h" -#include - -char HttpGet::hexcode[]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; - -HttpGet::HttpGet() : - nPort( 80 ), - sUserAgent("libbu++; HttpGet") -{ -} - -HttpGet::HttpGet( const std::string &url ) : - nPort( 80 ) -{ - setURL( url ); -} - -HttpGet::~HttpGet() -{ -} - -void HttpGet::setURL( const std::string &url ) -{ - int len = url.size(); - //printf("Full URL: %s\n", url.c_str() ); - int pos = url.find("://"); - sProto.assign( url, 0, pos ); - //printf("Protocol: %s\n", sProto.c_str() ); - - int pos2 = url.find("/", pos+3 ); - if( pos2 >= 0 ) - { - sHost.assign( url, pos+3, pos2-pos-3 ); - } - else - { - sHost.assign( url, pos+3, std::string::npos ); - } - - int pos3 = sHost.find(":"); - if( pos3 >= 0 ) - { - nPort = strtol( sHost.c_str()+pos3+1, NULL, 10 ); - sHost.erase( pos3 ); - } - //printf("Hostname: %s\n", sHost.c_str() ); - //printf("Port: %d\n", nPort ); - - pos3 = url.find("?", pos2+1 ); - if( pos3 >= 0 ) - { - sPath.assign( url, pos2, pos3-pos2 ); - //printf("Path: %s\n", sPath.c_str() ); - for(;;) - { - int end = pos3+1; - for(; url[end] != '=' && url[end] != '&' && end < len; end++ ); - std::string sKey, sValue; - sKey.assign( url, pos3+1, end-pos3-1 ); - if( url[end] == '=' ) - { - pos3 = end; - for( end++; url[end] != '&' && end < len; end++ ); - sValue.assign( url, pos3+1, end-pos3-1 ); - pos3 = end; - } - else - { - } - lParams.push_back( StringPair( sKey, sValue ) ); - //printf("Param: %s = %s\n", sKey.c_str(), sValue.c_str() ); - if( end+1 >= len ) break; - } - } - else - { - sPath.assign( url, pos2, std::string::npos ); - //printf("Path: %s\n", sPath.c_str() ); - } - - //printf("\n"); -} - -void HttpGet::addParam( const std::string &key, const std::string &value ) -{ - lParams.push_back( StringPair( key, value ) ); -} - -std::string HttpGet::escape( const std::string &src ) -{ - std::string escaped(""); - for( std::string::const_iterator i = src.begin(); i != src.end(); i++ ) - { - unsigned char j = *i; - if( (j >= '0' && j <= '9') || - (j >= 'a' && j <= 'z') || - (j >= 'A' && j <= 'Z') || - j == '$' || - j == '-' || - j == '_' || - j == '.' || - j == '+' || - j == '!' || - j == '*' || - j == '\'' || - j == '(' || - j == ')' ) - { - escaped += j; - } - else - { - escaped += "%"; - escaped += hexcode[j>>4]; - escaped += hexcode[j&0x0F]; - } - } - - return escaped; -} - -SBuffer *HttpGet::get() -{ - std::string sData; - sData = "GET " + sPath; - if( !lParams.empty() ) - { - sData += "?"; - for( std::list::iterator i = lParams.begin(); - i != lParams.end(); i++ ) - { - if( i != lParams.begin() ) - sData += "&"; - - if( (*i).second == "" ) - { - sData += escape( (*i).first ); - } - else - { - sData += escape( (*i).first ); - sData += "="; - sData += escape( (*i).second ); - } - } - } - - sData += " HTTP/1.1\r\n" - "User-Agent: " + sUserAgent + "\r\n" - "Connection: close\r\n" - "Host: " + sHost + "\r\n" - "Content-type: application/x-www-form-urlencoded\r\n\r\n"; - - //printf("Connection content:\n\n%s\n\n", sData.c_str() ); - - Connection con; - //printf("Opening connection...\n"); - con.open( sHost.c_str(), nPort ); - { - int nSocket = con.getSocket(); - fd_set rfds, wfds, efds; - int retval; - - FD_ZERO(&rfds); - FD_SET(nSocket, &rfds); - FD_ZERO(&wfds); - FD_SET(nSocket, &wfds); - FD_ZERO(&efds); - FD_SET(nSocket, &efds); - - struct timeval tv; - tv.tv_sec = 4; - tv.tv_usec = 0; - - //printf("Selecting on socket, can we read, write, etc?\n"); - retval = select( nSocket+1, &rfds, &wfds, &efds, &tv ); - /*printf("About to write: sock=%d, r=%d, w=%d, e=%d, ret=%d\n", - nSocket, - FD_ISSET( nSocket, &rfds ), - FD_ISSET( nSocket, &wfds ), - FD_ISSET( nSocket, &efds ), - retval - );*/ - - if( retval == 0 ) - { - //printf("Timeout on connection.\n"); - con.close(); - throw ExceptionBase("Connection Timeout on open.\n"); - } - - } - con.appendOutput( sData.c_str(), sData.size() ); - //printf("Writing to socket...\n"); - con.writeOutput(); - //printf("Data written...\n"); - int nSec = 5; - int nUSec = 0; - int nLastAmnt = con.getInputAmnt(); - try - { - double dTotTime = 0.0; - //printf("About to read input...\n"); - while( con.readInput( nSec, nUSec, &nSec, &nUSec ) ) - { - if( nLastAmnt == con.getInputAmnt() ) - { - if( nSec <= 0 && nUSec <= 0 ) - { - //printf("out of time, closing up.\n"); - con.close(); - throw ExceptionBase("Connection Timeout.\n"); - } - if( nSec == 5 && nUSec == 0 ) - { - //printf("No new data, breaking.\n"); - break; - } - } - else - { - dTotTime += (5.0-(nSec+nUSec/1000000.0)); - printf("\rRead %db at %.2fkb/sec", - con.getInputAmnt(), - ((double)(con.getInputAmnt())/1024.0) / dTotTime - ); - fflush( stdout ); - nSec = 5; - nUSec = 0; - nLastAmnt = con.getInputAmnt(); - } - } - } - catch( ConnectionException &e ) - { - //con.close(); - if( strcmp( e.what(), "Connection closed" ) ) - printf("\nConnectionException: %s\n", e.what() ); - } - - int total = con.getInputAmnt(); - const char *dat = con.getInput(); - //printf("\n===> Final size %d\n", total ); - for( int i = 0; i < total; i++ ) - { - if( !memcmp( dat+i, "\r\n\r\n", 4 ) ) - { - SBuffer *buf = new SBuffer; - buf->write( dat+i+4, total-i-4 ); - buf->setPos( 0 ); - con.close(); - return buf; - } - } - con.close(); - - //printf("\n\n%s\n\n", dat ); - - throw ExceptionBase("Something went wrong, incomplete response? fix this.\n"); -} - diff --git a/src/httpget.h b/src/httpget.h deleted file mode 100644 index 8272641..0000000 --- a/src/httpget.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef HTTP_GET_H -#define HTTP_GET_H - -#include -#include -#include -#include - -#include "sbuffer.h" - -class HttpGet -{ -public: - HttpGet(); - HttpGet( const std::string &url ); - virtual ~HttpGet(); - - void setURL( const std::string &url ); - void addParam( const std::string &key, const std::string &value ); - void setUserAgent( const std::string &sUserAgent ) - { - this->sUserAgent = sUserAgent; - } - void setHost( const std::string &sHost ) - { - this->sHost = sHost; - } - - std::string escape( const std::string &src ); - SBuffer *get(); - -private: - std::string sProto; - std::string sHost; - std::string sPath; - int nPort; - std::string sUserAgent; - typedef std::pair StringPair; - std::list lParams; - static char hexcode[]; - -}; - -#endif diff --git a/src/linkedlist.cpp b/src/linkedlist.cpp deleted file mode 100644 index a9902bc..0000000 --- a/src/linkedlist.cpp +++ /dev/null @@ -1,210 +0,0 @@ -#include "linkedlist.h" - -LinkedList::LinkedList( ) -{ - pBase = NULL; - pTop = NULL; - pLast = NULL; - nSize = 0; - nLast = -1; -} - -LinkedList::~LinkedList( ) -{ -/* - Link *pCur = pBase; - while( pCur ) - { - Link *pLast = pCur; - pCur = pCur->pNext; - delete pLast; - } -*/ - empty(); -} - -void *LinkedList::getAt( int index ) -{ - if( index < 0 || index >= nSize ) - return NULL; - - return getPtrTo( index )->pData; -} - -void LinkedList::append( void *data ) -{ - if( pBase == NULL ) - { - pBase = new Link( data ); - pTop = pBase; - nSize++; - } - else - { - pTop->pNext = new Link( data ); - pTop = pTop->pNext; - nSize++; - } -} - -void LinkedList::insertBefore( void *data, int pos ) -{ - if( pos < 0 || pos > nSize ) - return; - - if( pos == 0 ) - { - Link *pTmp = new Link( data, pBase ); - if( pBase == NULL ) - { - pTop = pTmp; - } - pBase = pTmp; - if( nLast >= 0 ) nLast++; - nSize++; - } - else - { - Link *pCur; - if( (pCur = getPtrTo( pos-1 )) == NULL ) - { - return; - } - Link *pNew = new Link( data, pCur->pNext ); - pCur->pNext = pNew; - if( pNew->pNext == NULL ) - { - pTop = pNew; - } - if( nLast >= pos ) nLast++; - nSize++; - } -} - -int LinkedList::getSize( ) -{ - return nSize; -} - -bool LinkedList::isEmpty( ) -{ - if( nSize == 0 ) - return true; - return false; -} - -void LinkedList::deleteAt( int index ) -{ - if( index >= nSize || - pBase == NULL ) - return; - - if( index == 0 ) - { - Link *pTmp = pBase->pNext; - delete pBase; - pBase = pTmp; - if( nLast >= 0 ) nLast--; - nSize--; - if( pBase == NULL ) - { - pTop = NULL; - } - else if( pBase->pNext == NULL ) - { - pTop = pBase; - } - } - else - { - Link *pCur = getPtrTo( index-1 ); - if( pCur->pNext == pTop ) - { - pTop = pCur; - } - Link *pTmp; - if( pCur->pNext == NULL ) - { - pTmp = NULL; - } - else - { - pTmp = pCur->pNext->pNext; - } - delete pCur->pNext; - pCur->pNext = pTmp; - if( nLast == index ) nLast = -1; - else if( index < nLast ) nLast--; - nSize--; - } -} - -void LinkedList::empty() -{ - while( nSize > 0 ) - { - deleteAt( 0 ); - } -} - -void LinkedList::setSize( int newSize ) -{ - if( newSize < nSize ) - { - // Delete items off of the end of the list. - while( nSize > newSize ) - { - deleteAt( nSize-1 ); - } - } - else - { - // Add null items to the end of the list. - while( nSize < newSize ) - { - append( NULL ); - } - } -} - -void LinkedList::setAt( int index, void *data ) -{ - if( index >= nSize || index < 0 ) - return; - - getPtrTo( index )->pData = data; -} - -LinkedList::Link *LinkedList::getPtrTo( int index ) -{ - if( index < 0 || index >= nSize ) - return NULL; - if( index == nLast ) - { - return pLast; - } - if( index == 0 ) - { - pLast = pBase; - nLast = 0; - return pBase; - } - else - { - Link *pCur = pBase; - int nCur = 0; - if( nLast < index && nLast >= 0 ) - { - pCur = pLast; - nCur = nLast; - } - while( nCur != index ) - { - pCur = pCur->pNext; - nCur++; - } - nLast = index; - pLast = pCur; - return pCur; - } -} diff --git a/src/linkedlist.h b/src/linkedlist.h deleted file mode 100644 index e430108..0000000 --- a/src/linkedlist.h +++ /dev/null @@ -1,87 +0,0 @@ -/**@file - * Describes the LinkedList implementation of the List ADT. - *@author Mike Buland - */ - -#ifndef LINKEDLIST_H -#define LINKEDLIST_H - -#include -#include "list.h" - -/** A linked-item implementation of the List ADT. Since the data is linked - * sequentially this is a great choice for lists that will grow and shrink - * a lot, but don't require as much random access. This implementation - * includes optomizations that make iterating through data, and appending - * items to the list take O(1) time. - *@author Mike Buland - */ -class LinkedList : public List -{ -public: - /** - * Construct a blank LinkedList. - */ - LinkedList(); - - /** - * Delete all list data, but do not delete any of the contained elements. - */ - virtual ~LinkedList(); - - void *getAt( int nIndex ); - void append( void *pData ); - void insertBefore( void *pData, int nPos = 0 ); - int getSize( ); - bool isEmpty( ); - void deleteAt( int nIndex ); - void empty(); - void setSize( int nNewSize ); - void setAt( int nIndex, void *pData ); - -private: - /** - * A link in the linked list. - */ - class Link - { - public: - /** - * Construct an empty link. - */ - Link() - { - pData = NULL; - pNext = NULL; - } - /** - * Construct a link filled in with useful data. - *@param newData The data this link should hold. - *@param newNext The next link that this link should point to. - */ - Link( void *newData = NULL, Link * newNext = NULL ) - { - pData = newData; - pNext = newNext; - } - void *pData; /**< A pointer to the contained data. */ - Link *pNext; /**< A pointer to the next link in the chain */ - }; - - /** - * Finds a pointer to the link at index index. This is the core function - * called for all seek operations, and has been optimized as heavily as - * possible. - *@param index The zero-based index of the desired element. - *@returns A pointer to the requested Link, or NULL if it isn't found. - */ - Link *getPtrTo( int index ); - Link *pBase; /**< The first link in the list. */ - Link *pTop; /**< The Last link in the list. */ - Link *pLast; /**< The previously requested link. */ - int nSize; /**< The number of contained links. */ - int nLast; /**< The index of the previously requested link. */ -}; - -#endif - diff --git a/src/linkmessage.cpp b/src/linkmessage.cpp deleted file mode 100644 index cf3df42..0000000 --- a/src/linkmessage.cpp +++ /dev/null @@ -1,44 +0,0 @@ -#include "linkmessage.h" -#include - -LinkMessage::LinkMessage( int nNewMsg ) -{ - nMsg = nNewMsg; -} - -LinkMessage::~LinkMessage() -{ -} - -/* -void LinkMessage::setBroadcast( bool bOn ) -{ - bBroadcast = bOn; -} - -bool LinkMessage::isBroadcast() -{ - return bBroadcast; -} - - -void LinkMessage::setFromID( int id ) -{ - nFromLinkID = id; -} - -int LinkMessage::getFromID() -{ - return nFromLinkID; -} - -void LinkMessage::setToID( int id ) -{ - nTargetLinkID = id; -} - -int LinkMessage::getToID() -{ - return nTargetLinkID; -} -*/ diff --git a/src/linkmessage.h b/src/linkmessage.h deleted file mode 100644 index 6cdfb2f..0000000 --- a/src/linkmessage.h +++ /dev/null @@ -1,39 +0,0 @@ -/**\file linkmessage.h - */ - -#ifndef LINKMESSAGE_H -#define LINKMESSAGE_H - -/** - * A message to be broadcast accross ProgramLinks in a ProgramChain. Generally - * one would make a subclass of this in order to transmit more useful - * information, but sometimes it isn't necesarry. - *@author Mike Buland - */ -class LinkMessage -{ -public: - /** - * Construct a blank LinkMessage. - */ - LinkMessage() {}; - - /** - * Deconstruct a LinkMessage. - */ - virtual ~LinkMessage(); - - /** - * Create a LinkMessage object with a specific message assosiated with it - * to start with. - *@param nNewMsg The message to use in the Message object. - */ - LinkMessage( int nNewMsg ); - - /** - * The message contained in the Message object. - */ - int nMsg; -}; - -#endif diff --git a/src/linkmessenger.cpp b/src/linkmessenger.cpp deleted file mode 100644 index 3bd401a..0000000 --- a/src/linkmessenger.cpp +++ /dev/null @@ -1,41 +0,0 @@ -#include "linkmessenger.h" - -LinkMessenger::LinkMessenger() : - pFirst( NULL ), - pLast( NULL ) -{ -} - -LinkMessenger::~LinkMessenger() -{ -} - -void LinkMessenger::enqueueMessage( LinkMessage *pMsg ) -{ - if( pLast == NULL ) - { - pFirst = pLast = new Link; - pLast->pMsg = pMsg; - pLast->pNext = NULL; - } - else - { - pLast->pNext = new Link; - pLast = pLast->pNext; - pLast->pMsg = pMsg; - pLast->pNext = NULL; - } -} - -LinkMessage *LinkMessenger::dequeueMessage() -{ - if( pFirst == NULL ) - return NULL; - - Link *pTmp = pFirst; - pFirst = pFirst->pNext; - LinkMessage *pRet = pTmp->pMsg; - delete pTmp; - return pRet; -} - diff --git a/src/linkmessenger.h b/src/linkmessenger.h deleted file mode 100644 index ed52639..0000000 --- a/src/linkmessenger.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef LINK_MESSENGER_H -#define LINK_MESSENGER_H - -#include -#include -#include "linkmessage.h" - -class LinkMessenger -{ -public: - LinkMessenger(); - virtual ~LinkMessenger(); - - void enqueueMessage( LinkMessage *pMsg ); - LinkMessage *dequeueMessage(); - bool hasMessages() - { - return (pFirst != NULL); - } - -private: - typedef struct Link - { - LinkMessage *pMsg; - Link *pNext; - }; - Link *pFirst; - Link *pLast; - -}; - -#endif diff --git a/src/list.cpp b/src/list.cpp deleted file mode 100644 index 18f1a66..0000000 --- a/src/list.cpp +++ /dev/null @@ -1,10 +0,0 @@ -#include "list.h" - -List::List( ) -{ -} - -List::~List( ) -{ -} - diff --git a/src/list.h b/src/list.h deleted file mode 100644 index c71b328..0000000 --- a/src/list.h +++ /dev/null @@ -1,101 +0,0 @@ -#ifndef LIST_H -#define LIST_H - - -/** The basic List class ADT. This, on it's own, does absolutely nothing, but - * does define all standard interface functions to access a list. - *@author Mike Buland - */ -class List -{ -public: - /** - * Construct a list. - */ - List(); - - /** - * Desconstruct a list. - */ - virtual ~List(); - - /** Gets the value at a specified index. - *@param nIndex The index of the item to return. - *@returns The specified item, or NULL if the index was beyond the range - * of the list. - *@author Mike Buland - */ - virtual void *getAt( int nIndex ) = 0; - - /** Append the given data to the end of the list. This increases the - * size of the list by one. - *@param pData The data to append to the list. - *@author Mike Buland - */ - virtual void append( void *pData ) = 0; - - /** Inserts an item at the specified position in the list. The - * new item takes the index that you specify, and all other items - * are moved up one position. The size of the list is increased by - * one. - *@param pData The value to insert into the list. - *@param nPos Where to insert the data into the list. - *@author Mike Buland - */ - virtual void insertBefore( void *pData, int nPos = 0 ) = 0; - - /** Determines the size of the list, in elements. - *@returns The size of the list. - *@author Mike Buland - */ - virtual int getSize( ) = 0; - - /** Determines if the list is empty or not. - *@returns True if the list is empty, or false if the list has - * data in it (if the size is greater than zero). - *@author Mike Buland - */ - virtual bool isEmpty( ) = 0; - - /** Deletes an item at the specified index and moves all other - * values down one index. The size of the list is decreased by one. - *@param nIndex The index of the item to delete. - *@author Mike Buland - */ - virtual void deleteAt( int nIndex ) = 0; - - /** Completely empties the list, and sets the effective size to - * zero. - *@author Mike Buland - */ - virtual void empty() = 0; - - /** Sets the size of the list. This can be larger or smaller - * than what it was previously. If larger, new blank items will - * be added to the end of the list. If smaller than the old list - * items will be deleted from the end. - *@param nNewSize The new size of the list. - *@author Mike Buland - */ - virtual void setSize( int nNewSize ) = 0; - - /** Sets a member at a specified location to a new value. - * If the member being set is outside of the range of the - * current list it should be expanded. - *@param nIndex The zero-based index of the item to change. - *@param pData The new value for that index. - *@author Mike Buland - */ - virtual void setAt( int nIndex, void *pData ) = 0; - - /** Makes the List work like an array. Just say listObj[2] to get - * the third element. - *@param nIndex The index to access in the list. - *@returns A pointer to the data at element index. - *@author Mike Buland - */ - void *operator[]( int nIndex ) { return getAt( nIndex ); }; -}; - -#endif - diff --git a/src/md5.cpp b/src/md5.cpp deleted file mode 100644 index c0cacdd..0000000 --- a/src/md5.cpp +++ /dev/null @@ -1,190 +0,0 @@ -#include -#include -#include -#include "md5.h" - -// This is a fun macro that tells us where the length char goes after the data -// section in the padded data segment. It's short for OBfuscation LOCaction. -#define OBLOC(len) ((((len + 64) >> 9) << 4) + 14) -// This performs a wrapping bitwise shift, kinda' fun! - -#define bit_roll( num, cnt ) \ - (((num) << (cnt)) | (((num) >> (32 - (cnt))) & ~(-1<<(cnt)))) - -//#define md5_cmn( q, a, b, x, s, t ) (bit_roll((a + q + x + t), s) + b) - -// The following are handy wrappers for the cmn function -#define md5_ff( a, b, c, d, x, s, t ) \ - (md5_cmn((b & c) | ((~b) & d), a, b, x, s, t)) - -#define md5_gg( a, b, c, d, x, s, t ) \ - (md5_cmn((b & d) | (c & (~d)), a, b, x, s, t)) - -#define md5_hh( a, b, c, d, x, s, t ) \ - (md5_cmn(b ^ c ^ d, a, b, x, s, t)) - -#define md5_ii( a, b, c, d, x, s, t ) \ - (md5_cmn(c ^ (b | (~d)), a, b, x, s, t)) - -inline long md5_cmn( long q, long a, long b, long x, long s, long t ) -{ - return bit_roll((a + q + x + t), s) + b; -} - -md5::md5() -{ -} - -md5::~md5() -{ -} - -/* - * Calculate the MD5 of an array of little-endian words, and a bit length - */ -void md5::core_md5( long *x, long len, md5sum *output ) -{ - long a = 1732584193, olda; - long b = -271733879, oldb; - long c = -1732584194, oldc; - long d = 271733878, oldd; - - for( long i = 0; i < len; i += 16 ) - { - olda = a; - oldb = b; - oldc = c; - oldd = d; - - a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936); - d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586); - c = md5_ff(c, d, a, b, x[i+ 2], 17, 606105819); - b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330); - a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897); - d = md5_ff(d, a, b, c, x[i+ 5], 12, 1200080426); - c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341); - b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983); - a = md5_ff(a, b, c, d, x[i+ 8], 7 , 1770035416); - d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417); - c = md5_ff(c, d, a, b, x[i+10], 17, -42063); - b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162); - a = md5_ff(a, b, c, d, x[i+12], 7 , 1804603682); - d = md5_ff(d, a, b, c, x[i+13], 12, -40341101); - c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290); - b = md5_ff(b, c, d, a, x[i+15], 22, 1236535329); - - a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510); - d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632); - c = md5_gg(c, d, a, b, x[i+11], 14, 643717713); - b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302); - a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691); - d = md5_gg(d, a, b, c, x[i+10], 9 , 38016083); - c = md5_gg(c, d, a, b, x[i+15], 14, -660478335); - b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848); - a = md5_gg(a, b, c, d, x[i+ 9], 5 , 568446438); - d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690); - c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961); - b = md5_gg(b, c, d, a, x[i+ 8], 20, 1163531501); - a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467); - d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784); - c = md5_gg(c, d, a, b, x[i+ 7], 14, 1735328473); - b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734); - - a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558); - d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463); - c = md5_hh(c, d, a, b, x[i+11], 16, 1839030562); - b = md5_hh(b, c, d, a, x[i+14], 23, -35309556); - a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060); - d = md5_hh(d, a, b, c, x[i+ 4], 11, 1272893353); - c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632); - b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640); - a = md5_hh(a, b, c, d, x[i+13], 4 , 681279174); - d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222); - c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979); - b = md5_hh(b, c, d, a, x[i+ 6], 23, 76029189); - a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487); - d = md5_hh(d, a, b, c, x[i+12], 11, -421815835); - c = md5_hh(c, d, a, b, x[i+15], 16, 530742520); - b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651); - - a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844); - d = md5_ii(d, a, b, c, x[i+ 7], 10, 1126891415); - c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905); - b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055); - a = md5_ii(a, b, c, d, x[i+12], 6 , 1700485571); - d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606); - c = md5_ii(c, d, a, b, x[i+10], 15, -1051523); - b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799); - a = md5_ii(a, b, c, d, x[i+ 8], 6 , 1873313359); - d = md5_ii(d, a, b, c, x[i+15], 10, -30611744); - c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380); - b = md5_ii(b, c, d, a, x[i+13], 21, 1309151649); - a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070); - d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379); - c = md5_ii(c, d, a, b, x[i+ 2], 15, 718787259); - b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551); - - a = a + olda; - b = b + oldb; - c = c + oldc; - d = d + oldd; - } - - output->data[0] = a; - output->data[1] = b; - output->data[2] = c; - output->data[3] = d; - delete[] x; -} - -long *md5::c2l( const char *str, long len, long *nNewLen ) -{ - long len8 = len*8; - long mlen = OBLOC( len8 ); - long flen = (((mlen/16)+((mlen%16)?(1):(0))))*16; - long *aBin = new long[flen]; - memset( aBin, 0, flen*4 ); - - for( long i = 0; i < len8; i+=8 ) - { - aBin[i>>5] |= ((long)str[i/8]) << (i%32); - } - - aBin[len8 >> 5] |= 0x80 << ((len8) % 32); - aBin[OBLOC( len8 )] = len8; - - (*nNewLen) = flen; - - return aBin; -} - -void md5::l2hexstr( long *binarray, char *str ) -{ - static const char hex_tab[] = {"0123456789abcdef"}; - //static char str[33]; - - int k = 0; - for( int i = 0; i < 16; i++) - { - str[k++] = hex_tab[(binarray[i>>2] >> ((i%4)*8+4)) & 0xF]; - str[k++] = hex_tab[(binarray[i>>2] >> ((i%4)*8 )) & 0xF]; - } -} - -void md5::sumString( md5sum *pSum, const char *sStr ) -{ - sumData( pSum, sStr, strlen( sStr ) ); -} - -void md5::sumData( md5sum *pSum, const char *aData, long nLen ) -{ - long nNewLen; - long *aOb = c2l( aData, nLen, &nNewLen ); - core_md5( aOb, nNewLen, pSum ); -} - -void md5::sumToHex( md5sum *pSum, char *sHex ) -{ - l2hexstr( pSum->data, sHex ); -} - diff --git a/src/md5.h b/src/md5.h deleted file mode 100644 index 7f77d83..0000000 --- a/src/md5.h +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef MD5_H -#define MD5_H - -/** - * Used to store an MD5 sum in a handy container. - */ -typedef struct -{ - /** The actual data-storage for an MD5 sum. */ - long data[4]; -} md5sum; - -/** - * Class for easily calculating MD5 sums of just about any data. - *@author Mike Buland - */ -class md5 -{ -public: - /** Build an MD5 sum builder. */ - md5(); - - /** Deconstruct */ - virtual ~md5(); - - /** - * Create a sum of a standard c string, null terminated. This is probably - * the easiest function to use. - *@param pSum The MD5 sum structure to fill up. - *@param sStr The null-terminated string to turn into an MD5 sum. - */ - void sumString( md5sum *pSum, const char *sStr ); - - /** - * Create a sum of an array of arbitrary data. This is the most handy for - * dealing with files and so on. - *@param pSum The MD5 sum structure to fill up. - *@param aData A pointer to the base of the data to sum. - *@param nLen The number of bytes to use in the sum. - */ - void sumData( md5sum *pSum, const char *aData, long nLen ); - - /** - * Convert an md5sum to standard hex representation. Make sure that sHex - * contains at least 17 characters of space. - *@param pSum The sum structure to convert to hex. - *@param sHex The string to store the hex value in. - */ - void sumToHex( md5sum *pSum, char *sHex ); - -private: - /** - * Do the bulk of the work of the md5 algorithm. - *@param x I'm not sure. I'll need to look it up. - *@param len The length of the data. - *@param output The sum structure to put the output in. - */ - void core_md5( long *x, long len, md5sum *output ); - - /** - * Convert an array of charaters to an array of longs in a very crafty way. - * This also applies standard MD5 obfuscation to the resulting array, and - * makes it fit within MD5 size constraints. - *@param str The data to convert. - *@param len The length of the data. - *@param nNewLen A pointer to a variable that will hold the new length of - * the resulting array of longs. - *@returns The newly obfuscated and resized long array. - */ - long *c2l( const char *str, long len, long *nNewLen ); - - /** - * Backend helper to convert an array of longs into a hex string. - *@param binarray The binary data to convert. - *@param str The string to store the hex string in. - */ - void l2hexstr( long *binarray, char *str ); - -}; - -#endif diff --git a/src/multilog.cpp b/src/multilog.cpp deleted file mode 100644 index 143ee89..0000000 --- a/src/multilog.cpp +++ /dev/null @@ -1,102 +0,0 @@ -#include "multilog.h" -#include -#include -#include -#include - -#include "multilogchannel.h" - -MultiLog::MultiLog() -{ - lChannel = new LinkedList(); - rEntry = new RingList( 150 ); - nEntriesLost = 0; -} - -MultiLog::~MultiLog() -{ - int nMax = lChannel->getSize(); - for( int j = 0; j < nMax; j++ ) - { - ((MultiLogChannel *)lChannel->getAt(j))->closeLog(); - delete ((MultiLogChannel *)lChannel->getAt(j)); - } - delete lChannel; - - for( int j = 0; j < rEntry->getSize(); j++ ) - { - delete (LogEntry *)rEntry->getAt( j ); - } - delete rEntry; -} -/* -void MultiLog::Log( int nLevel, const char *lpFormat, ...) -{ - switch( nLevel ) - { - default: - break; - } - va_list ap; - va_start(ap, lpFormat); - - vprintf( lpFormat, ap ); - - va_end(ap); -}*/ - -void MultiLog::DetailLog( int nLevel, const char *lpFile, int nLine, const char *lpFunction, const char *lpFormat, ...) -{ - LogEntry *e = new LogEntry(); - - va_list ap; - va_start(ap, lpFormat); - char *text; - vasprintf( &text, lpFormat, ap ); - va_end(ap); - - time( &e->xTime ); - e->nLevel = nLevel; - e->nLine = nLine; - e->lpFile = new char[strlen(lpFile)+1]; - strcpy( e->lpFile, lpFile ); - e->lpText = new char[strlen(text)+1]; - strcpy( e->lpText, text ); - free( text ); - - append( e ); -} - -void MultiLog::append( LogEntry *pEntry ) -{ - rEntry->append( pEntry ); - if( rEntry->getPushBuf() ) - { - delete (LogEntry *)rEntry->getPushBuf(); - nEntriesLost++; - } - - for( int j = 0; j < lChannel->getSize(); j++ ) - { - ((MultiLogChannel *)lChannel->getAt( j ))->append( pEntry ); - } -} - -void MultiLog::addChannel( MultiLogChannel *pChannel ) -{ - lChannel->append( pChannel ); - - pChannel->openLog(); - - for( int j = 0; j < rEntry->getSize(); j++ ) - { - pChannel->append( (LogEntry *)rEntry->getAt( j ) ); - } -} - -MultiLog::LogEntry::~LogEntry() -{ - delete[] lpFile; - delete[] lpText; -} - diff --git a/src/multilog.h b/src/multilog.h deleted file mode 100644 index 692095a..0000000 --- a/src/multilog.h +++ /dev/null @@ -1,130 +0,0 @@ -#ifndef MULTILOG_H -#define MULTILOG_H - -#include -#include -#include - -#include "ringlist.h" -#include "linkedlist.h" -#include "singleton.h" - -/** - * Calls the DetailLog function but includes pre-processor macros to fill in - * most of the fields for you. This makes your life a lot easier, and makes the - * log useful for system debugging as well as just letting people know what's - * going on. - *@param LEVEL The log level, comes from an enum in the MultiLog class. - *@param FORMAT The text to store in the log, using printf style formatting. - *@param ... Parameters to help format the text in the FROMAT param. - */ -#define LineLog( LEVEL, FORMAT, ...) DetailLog( LEVEL, __FILE__, __LINE__, __PRETTY_FUNCTION__, FORMAT, ##__VA_ARGS__ ) - -#define MultiLineLog( LEVEL, FORMAT, ...) MultiLog::getInstance().DetailLog( LEVEL, __FILE__, __LINE__, __PRETTY_FUNCTION__, FORMAT, ##__VA_ARGS__ ) - -/** MultiLog keeps track of logfile info in a myriad of varieties, and is - * easily configurable between them all. It allows output to the standard - * output, error output, files, networks, and streams, which includes memory - * buffers. - * MultiLog uses the singleton pattern to keep only a single instance of - * the log. Instead of instantiating a new copy, call the getLog method. - *@author Mike Buland - */ -class MultiLog : public Singleton -{ - friend class Singleton; -public: - /** - * Keeps track of a single log entry, in a standard format, that can be - * processed by any MultiLogChannel derrived class. - *@author Mike Buland - */ - typedef struct LogEntry - { - /** Safely delete a log entry. */ - virtual ~LogEntry(); - time_t xTime; /**< The time the log entry was made. */ - int nLevel; /**< The log-level of the entry. */ - char *lpFile; /**< The name of the file this entry came from. */ - int nLine; /**< The line number that this log came from. */ - char *lpText; /**< The text content of this log entry. */ - } LogEntry; - -protected: - /** - * Private constructor, this ensures that this is a singleton. - */ - MultiLog(); - - /** - * Destroy the multilog. - */ - virtual ~MultiLog(); - - /** - * Append a new logentry to the log list, possibly pushing an old entry off. - *@param pEntry The new entry to append. - */ - void append( LogEntry *pEntry ); - - /** - * The actual log entry storage mechanism. - */ - RingList *rEntry; - - /** - * The number of entries that have rolled off the end of the RingList. - */ - unsigned long nEntriesLost; - - /** - * A list of all channels that are registered with the MultiLog. - */ - LinkedList *lChannel; - -public: - - /** Sends info to the logfile. - *@param nLevel The type of data being logged (error, info, etc.) - *@param lpFormat The data to send to the log. - *@author Mike Buland - */ - //void Log( int nLevel, const char *lpFormat, ...); - - /** Sends info to the logfile with extra information, including the files - * that it was called from and the line in the code. Besides that, it's - * exactly the same as Log. Please use the LineLog macro to make DetailLog - * really easy to use. It operates exacly like Log, but inserts the - * builtin macros as the lpFile and nLine parameters. - *@param nLevel The type of data being logged (error, info, etc.) - *@param lpFile The name of the file that called the log function. - *@param nLine The line in the file that this log function was called from. - *@param lpFunction The name of the function that called the log function. - *@param lpFormat The data to send to the log. - *@author Mike Buland - */ - void DetailLog( int nLevel, const char *lpFile, int nLine, const char *lpFunction, const char *lpFormat, ...); - - /** - * Adds a logging channel to the MultiLog channel chain. Every added - * channel will automatically receive a complete log of everything that - * happened before the channel was added as well as all future messages. - *@param pChannel A pointer to the pre-contructed channel object to add. - */ - void addChannel( class MultiLogChannel *pChannel ); - - /** The various pre-defined levels available to use when logging. - * The person logging can make up their own, just make sure to remember - * which value is which (all levels are integers). - *@author Mike Buland - */ - enum Levels - { - LError, - LWarning, - LInfo, - LStatus - }; -}; - -#endif diff --git a/src/multilogchannel.cpp b/src/multilogchannel.cpp deleted file mode 100644 index ee4c9bf..0000000 --- a/src/multilogchannel.cpp +++ /dev/null @@ -1,13 +0,0 @@ -// -// C++ Implementation: multilogchannel -// -// Description: -// -// -// Author: Mike Buland , (C) 2005 -// -// Copyright: See COPYING file that comes with this distribution -// -// -#include "multilogchannel.h" - diff --git a/src/multilogchannel.h b/src/multilogchannel.h deleted file mode 100644 index d891a65..0000000 --- a/src/multilogchannel.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef MULTILOGCHANNEL_H -#define MULTILOGCHANNEL_H - -#include "multilog.h" - -/** - * The baseclass for any MultiLog output channel. Any class that implements - * all of these functions can be put in the log chain and will be sent - * messages from active MultiLoggers. - *@author Mike Buland - */ -class MultiLogChannel -{ -public: - /** - * Deconstruct a MultiLogChannel. - */ - virtual ~MultiLogChannel() {}; - - /** - * Should perform any operations that need to take place in order to start - * the output of data into this channel. This will be called once by the - * MultiLog when the MultiLogChannel is registered. - *@returns True means that everything can go as planned. False means that - * the MultiLog should remove this channel from the list and delete it. - */ - virtual bool openLog() = 0; - - /** - * Should append a log entry to the long, by whatever means are necesarry. - *@param pEntry The LogEntry to append. - *@returns True means that everything can go as planned. False means that - * the MultiLog should remove this channel from the list and delete it. - */ - virtual bool append( MultiLog::LogEntry *pEntry ) = 0; - - /** - * Should perform any operations that need to take place in order to safely - * close and cleanup the log. - *@returns True means that everything can go as planned. False means that - * the MultiLog should remove this channel from the list and delete it. - */ - virtual bool closeLog() = 0; -}; - -#endif diff --git a/src/multilogtext.cpp b/src/multilogtext.cpp deleted file mode 100644 index 4337cc9..0000000 --- a/src/multilogtext.cpp +++ /dev/null @@ -1,188 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include "multilogtext.h" -/* -bool fileexists( const char *sPath ) -{ - int nFileDesc = open( sPath, O_RDONLY ); - if( nFileDesc < 0 ) - { - return false; - } - else - { - close( nFileDesc ); - return true; - } -}*/ - -MultiLogText::MultiLogText( const char *sFileName, const char *lpFormat, bool bRotateLog, int nMaxLogs ) -{ - this->lpFormat = NULL; - /* - if( bRotateLog ) - { - if( fileexists( sFileName ) == false ) - { - return; - } - - int nLen = strlen( sFileName ); - char *buf = new char[nLen+6]; - sprintf( buf, "%s.", sFileName ); - - for( int j = 1; j < nMaxLogs; j++ ) - { - sprintf( &buf[nLen+1], "%d", j ); - if( !fileexists( buf ) ) - { - rename( sFileName, buf ); - break; - } - } - }*/ - - nFD = open( sFileName, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH ); - setLogFormat( lpFormat ); -} - -MultiLogText::MultiLogText( int nFileDesc, const char *lpFormat ) -{ - this->lpFormat = NULL; - nFD = nFileDesc; - setLogFormat( lpFormat ); -} - -MultiLogText::~MultiLogText() -{ - if( nFD != -1 ) - { - close( nFD ); - } - - delete[] lpFormat; -} - -bool MultiLogText::setLogFormat( const char *lpFormat ) -{ - char buf[200]; - int k = 0; - static char fmts[10][4]={ - {'y', 'd', '0', '1'}, - {'m', 'd', '0', '2'}, - {'d', 'd', '0', '3'}, - {'h', 'd', '0', '4'}, - {'M', 'd', '0', '5'}, - {'s', 'd', '0', '6'}, - {'l', 'd', '0', '7'}, - {'f', 's', '0', '8'}, - {'L', 'd', '0', '9'}, - {'t', 's', '1', '0'}, - }; - - for( int j = 0; lpFormat[j] != '\0'; j++ ) - { - if( lpFormat[j] == '%' ) - { - buf[k++] = '%'; - int nPlace = k++; - k++; - buf[k++] = '$'; - bool bDone = false; - for( j++; bDone == false; j++ ) - { - int l; - for( l = 0; l < 10; l++ ) - { - if( lpFormat[j] == fmts[l][0] ) - { - buf[nPlace] = fmts[l][2]; - buf[nPlace+1] = fmts[l][3]; - buf[k++] = fmts[l][1]; - bDone = true; - break; - } - } - if( l == 10 ) - { - buf[k++] = lpFormat[j]; - } - } - j--; - } - else - { - buf[k++] = lpFormat[j]; - } - } - buf[k++] = '\n'; - buf[k] = '\0'; - - if( this->lpFormat != NULL ) - { - delete[] this->lpFormat; - } - this->lpFormat = new char[k+1]; - strcpy( this->lpFormat, buf ); - - return true; -} - -bool MultiLogText::openLog() -{ - if( nFD == -1 ) - { - return false; - } - return true; -} - -bool MultiLogText::append( MultiLog::LogEntry *pEntry ) -{ - if( nFD == -1 ) - { - return false; - } - - char *line = NULL; - struct tm *pTime; - pTime = localtime( &pEntry->xTime ); - asprintf( - &line, - lpFormat, - pTime->tm_year+1900, - pTime->tm_mon+1, - pTime->tm_mday, - pTime->tm_hour, - pTime->tm_min, - pTime->tm_sec, - pEntry->nLevel, - pEntry->lpFile, - pEntry->nLine, - pEntry->lpText - ); - write( nFD, line, strlen(line) ); - free( line ); - - return true; -} - -bool MultiLogText::closeLog() -{ - if( nFD == -1 ) - { - return false; - } - // Don't close it if it's sdtout or errorout - if( nFD > 2 ) - { - close( nFD ); - } - nFD = -1; - return true; -} - diff --git a/src/multilogtext.h b/src/multilogtext.h deleted file mode 100644 index 197aef1..0000000 --- a/src/multilogtext.h +++ /dev/null @@ -1,70 +0,0 @@ -#ifndef MULTILOGTEXT_H -#define MULTILOGTEXT_H - -#include "multilogchannel.h" - -/** - * Simple MultiLogChannel that takes the logdata, formats it textually, and - * writes it to a text device, either a file or the screen, yay! This takes - * the place of the old standard logging facility. - * The entries in the format follow the standard printf % style, and are as - * follows: - *
    - *
  • %y - current year
  • - *
  • %m - current month
  • - *
  • %d - current day
  • - *
  • %h - current hour (24-hour format)
  • - *
  • %M - current minute
  • - *
  • %s - current seccond
  • - *
  • %l - Loglevel (numerical)
  • - *
  • %f - Filename
  • - *
  • %L - Line number
  • - *
  • %t - Full text of the log entry
  • - *
- *@author Mike Buland - */ -class MultiLogText : public MultiLogChannel -{ -public: - /** - * Construct a MultiLogText object around a specific filename and format. - * The file named by sFileName will be opened for writting in text+append - * mode. No existing data will be destroyed. - *@param sFileName The file to output log-data to. - *@param lpFormat The format using the above specifications to be used for - * every log entry. - */ - MultiLogText( const char *sFileName, const char *lpFormat, bool bRotateLog=false, int nMaxLogs=0 ); - - /** - * Construct a MultiLogText object around a specific file and format. - * The file descriptor passed in should describe an already opened and set- - * up file or device. This could easily be a socket or stdout or stderr. - *@param nFileDesc The already opened descriptor to send data to. - *@param lpFormat The format using the above specifications to be used for - * every log entry. - */ - MultiLogText( int nFileDesc, const char *lpFormat ); - - /** - * Destroy the object. - */ - virtual ~MultiLogText(); - - bool openLog(); - bool append( MultiLog::LogEntry *pEntry ); - bool closeLog(); - - /** - * Change the log format on the fly. - *@param lpFormat The new format to use for all future log entries. - *@returns True if everything was fine, false for catastrophic failure. - */ - bool setLogFormat( const char *lpFormat ); - -private: - int nFD; /**< The file descriptor we're writing to. */ - char *lpFormat; /**< The format that we're using, converted for printf. */ -}; - -#endif 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 @@ +#include "arraylist.h" +#include +#include + +ArrayList::ArrayList( int initSize, int growByFactor ) +{ + apData = new void *[initSize]; + nSize = 0; + nCapacity = initSize; + nGrowByFactor = growByFactor; +} + +ArrayList::~ArrayList( ) +{ + delete[] apData; +} + +void *ArrayList::getAt( int index ) +{ + if( index < 0 || index > nSize ) + return NULL; + + return apData[index]; +} + +void ArrayList::append( void *data ) +{ + insertBefore( data, nSize ); +} + +void ArrayList::insertBefore( void *data, int pos ) +{ + if( pos < 0 || pos > nSize ) + return; + + checkResize(); + memmove( &apData[pos+1], &apData[pos], (nSize-pos)*sizeof(void*) ); + apData[pos] = data; + nSize++; +} + +int ArrayList::getSize( ) +{ + return nSize; +} + +bool ArrayList::isEmpty( ) +{ + return nSize==0; +} + +void ArrayList::deleteAt( int index ) +{ + if( index < 0 || index >= nSize ) + return; + + memmove( &apData[index], &apData[index+1], (nSize-index-1)*sizeof(void *) ); + nSize--; +} + +void ArrayList::empty() +{ + // Probably the easiest as far as things go. + nSize = 0; +} + +void ArrayList::resizeTo( int newSize ) +{ + void **apNew = new void *[newSize]; + memmove( apNew, apData, nSize*sizeof(void *) ); + nCapacity = newSize; + delete[] apData; + apData = apNew; +} + +void ArrayList::checkResize() +{ + if( nSize >= nCapacity ) + { + resizeTo( nCapacity + nGrowByFactor ); + } +} + +void ArrayList::setSize( int newSize ) +{ + if( newSize < 0 ) + return; + + nSize = newSize; + checkResize(); +} + +void ArrayList::setAt( int index, void *data ) +{ + if( index < 0 || index >= nSize ) + return; + + apData[index] = data; +} + 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 @@ +/** \file arraylist.h + * Describes the ArrayList class. + *@author Mike Buland + */ +#ifndef ARRAY_LIST_H +#define ARRAY_LIST_H + +#include "list.h" + +/** A simple list which uses an array. This is a great choice if you won't do + * a lot of adding and deleting and need a fast random access list. Otherwise + * use the LinkedList. + *@author Mike Buland + */ +class ArrayList : public List +{ +public: + /** Creates an arraylist with some pre-defined specs spelled out. + *@param initSize the inital number of elements to allocate. + *@param growByFactor How much to increase the size of the array by + * each time we run out of room. + */ + ArrayList( int initSize=100, int growByFactor=10 ); + /** + * Destroy the ArrayList + */ + virtual ~ArrayList(); + + void *getAt( int nIndex ); + void append( void *pData ); + void insertBefore( void *pData, int nPos = 0 ); + int getSize( ); + bool isEmpty( ); + void deleteAt( int nIndex ); + void empty(); + void setSize( int nNewSize ); + void setAt( int nIndex, void *pData ); + +private: + /** + * Checks to see if the system needs to be resized, if it does, this will + * automatically resize based on your parameters. + */ + void checkResize(); + + /** + * Resize the system to a specified size. If it is larger, then all data + * will be retained, if smaller the elements at the end will be cut off. + *@param newSize The number of elements to include after resizing. + */ + void resizeTo( int newSize ); + + /** + * Actual master array of pointers. This is done to follow the List specs. + * All data transactions are performed with pointers or compatable + * primitive data-types. + */ + void **apData; + + /** + * The number of filled in elements in the array. This is the practical + * real size of the ArrayList for all userspace applications. + */ + int nSize; + + /** + * The number of elements allocated in memory. Not all of these have to be + * filled in, and it is usually larger than nSize so that adding and + * deleting elements is fast and easy. + */ + int nCapacity; + + /** + * The amount to grow by whenever the array needs resizing. + */ + int nGrowByFactor; +}; + +#endif + 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 @@ +#include +#include +#include +#include +#include + +#include "cgi.h" + +Cgi::Cgi( const char *strSource ) : + aContent( new HashFunctionString(), 151, true ) +{ + int length, j, k, mode = 0, slen = 0; + char hexbuf[3] = { 0, 0, 0 }; + char *buf, chr; + Item *cur = NULL; + int nCur = 0; + + if( strSource != NULL ) + { + loadContent( strSource ); + } + + if( ( getenv( "CONTENT_LENGTH" ) ) ) + { + if( !strcmp + ( getenv( "CONTENT_TYPE" ), + "application/x-www-form-urlencoded" ) ) + { + length = atoi( getenv( "CONTENT_LENGTH" ) ); + buf = new char[length + 1]; + fread( buf, 1, length, stdin ); + cur = new Item( ); + aVars.append( cur ); + cur->type = VAR_STDINPUT; + for( j = 0; j < length; j++ ) + { + switch ( buf[j] ) + { + case '=': + cur->name = new char[slen + 1]; + slen = 0; + break; + + case '&': + cur->value = new char[slen + 1]; + cur->len = slen; + slen = 0; + cur = new Item( ); + aVars.append( cur ); + cur->type = VAR_STDINPUT; + break; + + default: + switch ( buf[j] ) + { + case '%': /* per-cents mean a hex-code for an ASCII char */ + j += 2; + slen++; + break; + + default: /* Nothing special, move along, folks... */ + slen++; + break; + } + break; + } + } + cur->value = new char[slen + 1]; + cur->len = slen; + slen = 0; + mode = 0; + cur = ( Item * ) aVars.getAt( 0 ); + k = 0; + nCur = 0; + for( j = 0; j < length; j++ ) + { + switch ( buf[j] ) + { + case '=': + mode = 1; + k = 0; + break; + + case '&': + mode = 0; + k = 0; + nCur++; + cur = ( Item * ) aVars.getAt( nCur ); + break; + + default: + switch ( buf[j] ) + { + case '%': /* per-cents mean a hex-code for an ASCII char */ + hexbuf[0] = buf[++j]; + hexbuf[1] = buf[++j]; + chr = ( char ) ( strtol( hexbuf, NULL, 16 ) ); + break; + + case '+': /* Pluses mean spaces, odd, I know... */ + chr = ' '; + break; + + default: /* Nothing special, move along, folks... */ + chr = buf[j]; + break; + } + if( mode == 0 ) + { + cur->name[k] = chr; + cur->name[++k] = '\0'; + } + else + { + cur->value[k] = chr; + cur->value[++k] = '\0'; + } + break; + } + } + delete buf; + } + else if( !strncmp + ( getenv( "CONTENT_TYPE" ), "multipart/form-data;", 20 ) ) + { + char *boundary, *oname; + int blen, j, k, olen; + + length = atoi( getenv( "CONTENT_LENGTH" ) ); + buf = new char[length + 1]; + fread( buf, 1, length, stdin ); + for( blen = 0; buf[blen + 1] != '\n'; blen++ ); + boundary = new char[blen + 1]; + memcpy( boundary, buf, blen ); + boundary[blen] = '\0'; + j = blen + 2; + for( ;; ) + { + cur = new Item( ); + aVars.append( cur ); + cur->type = VAR_STDINPUT; + if( !strncmp + ( buf + j, "Content-Disposition: form-data; name=\"", + 38 ) ) + { + j += 38; + for( k = 0; buf[j + k] != '\"'; k++ ); + oname = cur->name = new char[k + 1]; + memcpy( cur->name, buf + j, k ); + olen = k; + cur->name[k] = '\0'; + j += k + 1; + if( !strncmp( buf + j, "; filename=\"", 12 ) ) /* Must be a file */ + { + /* Acquire file name */ + j += 12; + for( k = 0; buf[j + k] != '\"'; k++ ); + cur->value = new char[k + 1]; + memcpy( cur->value, buf + j, k ); + cur->value[k] = '\0'; + cur->len = k; + j += k + 3; + + /* Acquire content type */ + if( !strncmp( "Content-Type: ", buf + j, 14 ) ) + { + j += 14; + cur = new Item( ); + aVars.append( cur ); + cur->type = VAR_STDINPUT; + cur->name = new char[olen + 1]; + memcpy( cur->name, oname, olen + 1 ); + for( k = 0; buf[j + k + 1] != '\n'; k++ ); + cur->value = new char[k + 1]; + memcpy( cur->value, buf + j, k ); + cur->value[k] = '\0'; + cur->len = k; + j += k; + } + else + { + cur = new Item( ); + aVars.append( cur ); + cur->type = VAR_STDINPUT; + cur->name = new char[olen + 1]; + memcpy( cur->name, oname, olen + 1 ); + cur->value = new char[1]; + cur->value[0] = '\0'; + cur->len = 0; + } + j += 4; + + /* Acquire content */ + cur = new Item( ); + aVars.append( cur ); + cur->type = VAR_STDINPUT; + cur->name = new char[olen + 1]; + memcpy( cur->name, oname, olen + 1 ); + if( !strncmp( buf + j + k, boundary, blen ) ) + { + cur->value = new char[1]; + cur->value[0] = '\0'; + j += blen + 4; + } + else if( !strncmp( buf + j + k + 1, boundary, blen ) ) + { + cur->value = new char[1]; + cur->value[0] = '\0'; + j += blen + 5; + } + else + { + for( k = 0; + strncmp( buf + j + k + 2, boundary, blen ); + k++ ); + cur->value = new char[k + 1]; + memcpy( cur->value, buf + j, k ); + cur->value[k] = '\0'; + cur->len = k; + j += k + blen + 4; + } + } + else + { + j += 4; + for( k = 0; + strncmp( buf + j + k + 2, boundary, blen ); + k++ ); + cur->value = new char[k + 1]; + memcpy( cur->value, buf + j, k ); + cur->value[k] = '\0'; + cur->len = k; + j += k + blen + 4; + } + if( buf[j + 1] == '\n' ) + j += 2; + if( j >= length ) + break; + } + else + { + cur->name = ( char * ) "ERROR"; + cur->value = ( char * ) "Error here"; + } + } + } + delete buf; + } + + if( ( buf = getenv( "HTTP_COOKIE" ) ) ) + { + int lbase = aVars.getSize( ); + length = strlen( buf ); + cur = new Item( ); + aVars.append( cur ); + cur->type = VAR_COOKIE; + for( j = 0; j < length; j++ ) + { + switch ( buf[j] ) + { + case '=': + cur->name = new char[slen + 1]; + slen = 0; + break; + + case ';': + cur->value = new char[slen + 1]; + cur->len = slen; + slen = 0; + cur = new Item( ); + aVars.append( cur ); + cur->type = VAR_COOKIE; + break; + + default: + switch ( buf[j] ) + { + case '%': /* per-cents mean a hex-code for an ASCII char */ + j += 2; + slen++; + break; + + default: /* Nothing special, move along, folks... */ + slen++; + break; + } + break; + } + } + cur->value = new char[slen + 1]; + cur->len = slen; + slen = 0; + cur = ( Item * ) aVars.getAt( lbase ); + mode = 0; + k = 0; + nCur = lbase; + for( j = 0; j < length; j++ ) + { + switch ( buf[j] ) + { + case '=': + mode = 1; + k = 0; + break; + + case ';': + mode = 0; + k = 0; + nCur++; + cur = ( Item * ) aVars.getAt( nCur ); + break; + + default: + switch ( buf[j] ) + { + case '%': /* per-cents mean a hex-code for an ASCII char */ + hexbuf[0] = buf[++j]; + hexbuf[1] = buf[++j]; + chr = ( char ) ( strtol( hexbuf, NULL, 16 ) ); + break; + + case '+': /* Pluses mean spaces, odd, I know... */ + chr = ' '; + break; + + case ' ': + continue; + break; + + default: /* Nothing special, move along, folks... */ + chr = buf[j]; + break; + } + if( mode == 0 ) + { + cur->name[k] = chr; + cur->name[++k] = '\0'; + } + else + { + cur->value[k] = chr; + cur->value[++k] = '\0'; + } + break; + } + } + } + + if( ( buf = getenv( "QUERY_STRING" ) ) ) + { + if( strlen( buf ) > 0 ) + { + int lbase = aVars.getSize( ); + length = strlen( buf ); + cur = new Item( ); + aVars.append( cur ); + cur->type = VAR_CMDLINE; + for( j = 0; j < length; j++ ) + { + switch ( buf[j] ) + { + case '=': + cur->name = new char[slen + 1]; + slen = 0; + break; + + case '&': + cur->value = new char[slen + 1]; + cur->len = slen; + slen = 0; + cur = new Item( ); + aVars.append( cur ); + cur->type = VAR_CMDLINE; + break; + + default: + switch ( buf[j] ) + { + case '%': /* per-cents mean a hex-code for an ASCII char */ + j += 2; + slen++; + break; + + default: /* Nothing special, move along, folks... */ + slen++; + break; + } + break; + } + } + cur->value = new char[slen + 1]; + cur->len = slen; + slen = 0; + cur = ( Item * ) aVars.getAt( lbase ); + nCur = lbase; + mode = 0; + k = 0; + for( j = 0; j < length; j++ ) + { + switch ( buf[j] ) + { + case '=': + mode = 1; + k = 0; + break; + + case '&': + mode = 0; + k = 0; + nCur++; + cur = ( Item * ) aVars.getAt( nCur ); + break; + + default: + switch ( buf[j] ) + { + case '%': /* per-cents mean a hex-code for an ASCII char */ + hexbuf[0] = buf[++j]; + hexbuf[1] = buf[++j]; + chr = ( char ) ( strtol( hexbuf, NULL, 16 ) ); + break; + + case '+': /* Pluses mean spaces, odd, I know... */ + chr = ' '; + break; + + default: /* Nothing special, move along, folks... */ + chr = buf[j]; + break; + } + if( mode == 0 ) + { + cur->name[k] = chr; + cur->name[++k] = '\0'; + } + else + { + cur->value[k] = chr; + cur->value[++k] = '\0'; + } + break; + } + } + } + } +} + +Cgi::~Cgi( ) +{ +} + +char *Cgi::getVarValue( const char *name, int skip, unsigned char type ) +{ + for( int j = 0; j < aVars.getSize( ); j++ ) + { + Item *cur = ( Item * ) aVars.getAt( j ); + if( !strcmp( cur->name, name ) ) + { + if( ( cur->type & type ) ) + { + if( skip <= 0 ) + { + return cur->value; + } + else + { + skip--; + } + } + } + } + return NULL; +} + +int Cgi::getVarLength( const char *name, int skip, unsigned char type ) +{ + for( int j = 0; j < aVars.getSize( ); j++ ) + { + Item *cur = ( Item * ) aVars.getAt( j ); + if( !strcmp( cur->name, name ) ) + { + if( ( cur->type & type ) ) + { + if( skip <= 0 ) + { + return cur->len; + } + else + { + skip--; + } + } + } + } + return -1; +} + +void Cgi::writeDebugInfo() +{ + printf( "
\n" );
+    printf( "0x%02X - stdInput | 0x%02X - cookie | 0x%02X - cmdLine\n\n",
+             VAR_STDINPUT, VAR_COOKIE, VAR_CMDLINE );
+    for( int j = 0; j < aVars.getSize(  ); j++ )
+    {
+        Item *item = ( Item * ) aVars.getAt( j );
+        printf("[%s] = \"%s\" [0x%02X]\n", item->name,
+                 item->value, item->type );
+    }
+    printf( "
\n" ); +} + +void Cgi::writeContentHeader( int type ) +{ + switch( type ) + { + case headerHTML: + printf("Content-type: text/html\n\n"); + break; + } +} + +void Cgi::writeContent( const char *name, ...) +{ + char *templ = (char *)aContent.get(name); + + if( templ ) + { + va_list ap; + + va_start (ap, name); + vprintf (templ, ap); + va_end (ap); + } + else + { + printf("Error finding content labeled \"%s\"\n", name ); + } +} + +void Cgi::loadContent( const char *strSource ) +{ + FILE *fh = NULL; + if( strSource == NULL ) + { + extern char *program_invocation_short_name; + char *tmpName = new char[strlen(program_invocation_short_name)+10]; + memset( tmpName, 0, strlen(program_invocation_short_name)+10 ); + strcpy( tmpName, program_invocation_short_name ); + strcat( tmpName, ".content" ); + fh = fopen( tmpName, "rt" ); + delete tmpName; + } + else + { + fh = fopen( strSource, "rt" ); + } + + if( fh == NULL ) return; + + struct stat xStats; + + fstat( fileno( fh ), &xStats ); + + char *bigBuf = new char[xStats.st_size+1]; + memset( bigBuf, 0, xStats.st_size+1 ); + fread( bigBuf, 1, xStats.st_size, fh ); + fclose( fh ); + + // Now we can actually load stuff from the file, first we need to make us up a format... + int lSize=0; + struct Content + { + char *name; + char *value; + } xCont; + int j = 0; + while( j < xStats.st_size ) + { + // We're looking for a content-block init statement + for( ; j < xStats.st_size; j++ ) + { + if( bigBuf[j] == '#' ) + { + if( bigBuf[j+1] == '{' ) + { + break; + } + } + } + j=j+2; + if( j >= xStats.st_size ) break; + for( ; bigBuf[j] == ' ' || bigBuf[j] == '\t'; j++ ); + for( lSize = 0; lSize+j < xStats.st_size && bigBuf[lSize+j] != '\n' && bigBuf[lSize+j] != '\r'; lSize++ ); + xCont.name = new char[lSize+1]; + memset( xCont.name, 0, lSize+1 ); + memcpy( xCont.name, &bigBuf[j], lSize ); + j += lSize+1; + + for( lSize = 0; lSize+j < xStats.st_size; lSize++ ) + { + if( bigBuf[lSize+j] == '#' ) + { + if( bigBuf[lSize+j+1] == '}' ) + { + break; + } + } + } + xCont.value = new char[lSize+1]; + memset( xCont.value, 0, lSize+1 ); + memcpy( xCont.value, &bigBuf[j], lSize ); + + aContent.insert( xCont.name, xCont.value ); + + j += lSize + 2; + } +} + +void Cgi::writeCookie( char const *name, char const *value, char const *expires, char const *path, char const *domain, bool secure ) +{ + printf("Set-Cookie: %s=%s", name, value ); + + if( expires != NULL ) + { + printf("; expires=%s", expires ); + } + + if( path != NULL ) + { + printf("; path=%s", path ); + } + + if( domain != NULL ) + { + printf("; domain=%s", domain ); + } + + if( secure ) + { + printf("; secure"); + } + + printf("\n"); +} 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 @@ +/**\file cgi.h + * Describes extra params needed to use the Cgi class as well as the class + * itself. + *@author Mike Buland + */ + +#include "linkedlist.h" +#include "hashtable.h" +#include "hashfunctionstring.h" + +#define VAR_STDINPUT 0x01 /**< Variable came from stdinput, web form */ +#define VAR_COOKIE 0x02 /**< Variable came from a cookie */ +#define VAR_CMDLINE 0x04 /**< Variable came from commandline / uri */ +#define VAR_ANY 0xFF /**< Mask including all other types */ + +/** + * Cgi header processor originally designed for apache cgi programs. When used + * from apache with what I beleive are some sort of standard set of command + * line parameters and environment variables. This always worked for all of my + * purposes. This class will automatically extract all data from the system + * that you need and places it into tables and things for easy access. + * There are three types of input that data can come from, StandardInput, + * CommandLine, and Cookies. StandardInput is when you get formdata in + * multi-part forms, Cookies should usually be cookies that you set, and + * command line is everything after the question mark in the URL. + * This also contains some simple helpers for putting templated data into the + * HTTP data feed. + *@author Mike Buland + */ +class Cgi +{ +public: + /** + * Create a complete CGI object, this object will automatically read data + * from all available sources and be ready for use on the very next line! + * If strSource is filled in it will also automatically read in a content + * file, which is a simple file format containing named blocks of reusable + * templates. + *@param strSource Set to a filename in order to load up a content file. + */ + Cgi( const char *strSource = NULL ); + + /** + * Destroy the cgi object. + */ + virtual ~Cgi( ); + + /** + * Get's the value for a variable as a character string. The name is the + * name that was given on the URL or in the form or cookie. Skip can be + * set to any value above zero to retreive subsequent variables with the + * same name. The most obvious use of this is when dealing with file + * uploads, each file upload sends you three variables with the same name + * and different content. Finally the variable type determines where you + * will accept this variable from. This is generally a bit of a security + * thing, if you store login info in a cookie and don't want people getting + * in by faking the appropriate URL. + *@param name The name of the variable you wish to retreive. + *@param skip THe number of variables with the given name to skip before + * returning something meaningful. The only way to determine how many + * variables with the same name there are is to skip until you get a NULL + * value returned. + *@param type Can be set to any combination of VAR_STDINPUT, VAR_COOKIE, + * VAR_CMDLINE, or just VAR_ANY. This takes bitflags, so you can or the + * values together. If a variable is found but came from the wrong source + * it won't match any other criteria and will be treated as though it + * doesn't exist. + *@returns A null-terminated string representing the value of the requested + * variable, or NULL if the variable did not exist. If a variable does + * exist but has no value the string returned will start with a NULL char, + * but be a valid string. + */ + char *getVarValue( const char *name, int skip=0, unsigned char type=VAR_ANY ); + + /** + * This functions identically in every way to getVarValue, except that + * instead of returning a pointer to the variable's value, it returns the + * length of the variable's value string. The params are the same and so + * a call to both functions with the same params should yeild a value and + * a corresponding length. + *@param name The name of the variable you wish to retreive. + *@param skip THe number of variables with the given name to skip before + * returning something meaningful. The only way to determine how many + * variables with the same name there are is to skip until you get a NULL + * value returned. + *@param type Can be set to any combination of VAR_STDINPUT, VAR_COOKIE, + * VAR_CMDLINE, or just VAR_ANY. This takes bitflags, so you can or the + * values together. If a variable is found but came from the wrong source + * it won't match any other criteria and will be treated as though it + * doesn't exist. + *@returns The length of the value-string of the requested variable. If + * the requested variable is not found, -1 is returned. + */ + int getVarLength( const char *name, int skip=0, unsigned char type=VAR_ANY ); + + /** + * A handy little function that writes a load of debug info related to + * parsing CGI params to the standard output in html. This is generally + * best used at the end of a page. + */ + void writeDebugInfo(); + + /** + * Write a content header to the standard output. This should also be the + * first thing that you do (except for writing cookies) after initializing + * the Cgi class. You can select a type of header or content from the + * header enum, and a properly formatted header will show up on the + * standard output. + *@param type Any value from the header enum in this class. The default is + * to write an html header, probably the most common as well. + */ + void writeContentHeader( int type=headerHTML ); + + /** + * Write content to the stnadard output. The content variable should have + * been loaded during construction of the Cgi object or with the + * loadContent function. The content variable should be formatted just like + * a printf string, so that anything you want to put into it will have a % + * symbol replacement code, like %s, %d, etc. Since this actually uses a + * type of printf function everything from those docs work here. + *@param name The name of the content variable to format and write to + * stnadard output. + *@param ... As many params as you want to include, ala printf. + */ + void writeContent( const char *name, ...); + + /** + * Load a content file. I don't want to describe the format here, you can + * just read the code or find an example for now. Sorry. + *@param strSource The name of the file to open and read in to get the + * content loaded. + */ + void loadContent( const char *strSource = NULL ); + + /** + * Write a cookie-set header to the output stream. This should be done + * before any other content-headers are written. The specifics of this + * function are very simple, since I rely on the user's understanding of + * how standard HTTP/1.1 or HTTP/1.0 cookie syntax works. If you don't + * care then just use the name and value and the defaults should keep you + * in good stead for a long time. + *@param name The name of the cookie variable to set. + *@param value The value to set to that variable. + *@param expires The formatted string value for the date and time this + * cookie should expire. A NULL here will put a "until the browser closes" + * tag in. + *@param path The path (URL) that this cookie belongs to. If you run a lot + * of hosted servers or sub-sites that may have some shared URL bits then + * you may want to set this. The cookie should only be sent to URL's that + * match this as their first part. + *@param domain The domain that is allowed to read this, if not set, it's + * the domain the web browser contacted when they got the cookie. + *@param secure I'm not sure, I think it's something to tell if the cookie + * is safe to keep because any potentially valuable data is encypted or + * otherwise unusable. I could be wrong. + */ + void writeCookie( char const *name, char const *value, char const *expires=NULL, char const *path=NULL, char const *domain=NULL, bool secure=false ); + + /** + * A simple helper class to contain variable data. + */ + class Item + { + public: + /** + * Build an empty Item. + */ + Item( ) + { + name = NULL; + value = NULL; + len = 0; + type = 0; + } + /** The name of the item. */ + char *name; + /** The value of the item. */ + char *value; + /** The length of the item's value. */ + unsigned long len; + /** The type of the item (where it came from). */ + unsigned char type; + }; + + /** Header values */ + enum + { + headerHTML + }; + +private: + /** Keeps track of all contained variables. */ + LinkedList aVars; + /** Keeps track of all content variables. */ + HashTable aContent; +}; 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 @@ +#include +#include +#include "xmlnode.h" +#include "xmlfilereader.h" +#include "configmanagerbase.h" + +ConfigManagerBase::ConfigManagerBase() +{ +} + +ConfigManagerBase::~ConfigManagerBase() +{ +} + +void ConfigManagerBase::addSearchPath( const std::string &sPath ) +{ + lSearchPath.push_back( sPath ); +} + +void ConfigManagerBase::loadConfig( const std::string &sFileName, const char *lpProfile ) +{ + // Try a few locations... + std::list::const_iterator i; + for( i = lSearchPath.begin(); i != lSearchPath.end(); i++ ) + { + if( parseConfig( (*i + sFileName).c_str(), lpProfile ) ) + { + break; + } + } +} + +bool ConfigManagerBase::parseConfig( const char *lpFileName, const char *lpProfile ) +{ + XmlNode *pRoot, *pCur; + XmlFileReader doc( lpFileName ); + + pRoot = doc.getRoot(); + if( pRoot == NULL ) + { + return false; + } + + if( strcmp("config", pRoot->getName() ) ) + { + return false; + } + + for( int j = 0;; j++ ) + { + pCur = pRoot->getChild( "profile", j ); + if( pCur == NULL ) + return false; + + if( !strcmp( pCur->getProperty("id"), lpProfile ) ) + { + return processProfile( pCur ); + } + } + + return false; +} + 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 @@ +#ifndef CONFIG_MANAGER_BASE_H +#define CONFIG_MANAGER_BASE_H + +#include +#include + +class ConfigManagerBase +{ +public: + ConfigManagerBase(); + virtual ~ConfigManagerBase(); + +public: + void addSearchPath( const std::string &sPath ); + void loadConfig( const std::string &sFileName, const char *lpProfile="default" ); + +private: + bool parseConfig( const char *lpFileName, const char *lpProfile ); + virtual bool processProfile( class XmlNode *pBase )=0; + + std::list lSearchPath; +}; + +#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 @@ +#include "confpair.h" + 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 @@ +#ifndef CONF_PAIR_H +#define CONF_PAIR_H + +#include +#include +#include +#include "confpairbase.h" + +/** + * + */ +template +class ConfPair : public ConfPairBase +{ +public: + ConfPair( const std::string &sName ) : + sName( sName ) + { } + + virtual ~ConfPair() + { } + + T &value() + { + return tValue; + } + + const std::string &name() + { + return sName; + } + + virtual void setFromString( const std::string &sStr ) + { + std::stringstream(sStr) >> tValue; + } + + virtual std::string getAsString() + { + std::stringstream tmp; + tmp << tValue; + return tmp.str(); + } + +private: + std::string sName; + T tValue; +}; + +template<> +void ConfPair::setFromString( const std::string &sStr ) +{ + tValue = sStr; +} + +template<> +std::string ConfPair::getAsString() +{ + return tValue; +} + +template<> +void ConfPair::setFromString( const std::string &sStr ) +{ + if( !strcasecmp( sStr.c_str(), "true" ) || + !strcasecmp( sStr.c_str(), "yes" ) || + !strcasecmp( sStr.c_str(), "on" ) ) + tValue = true; + else + tValue = false; +} + +template<> +std::string ConfPair::getAsString() +{ + if( tValue == true ) + return "True"; + return "False"; +} + +#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 @@ +#include "confpairbase.h" + +ConfPairBase::ConfPairBase() +{ +} + +ConfPairBase::~ConfPairBase() +{ +} + +ConfPairBase &ConfPairBase::operator=( const std::string &s ) +{ + setFromString( s ); + + return *this; +} + 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 @@ +#ifndef CONF_PAIR_BASE_H +#define CONF_PAIR_BASE_H + +#include +#include +#include +#include + +class ConfPairBase +{ +public: + ConfPairBase(); + virtual ~ConfPairBase(); + + virtual void setFromString( const std::string &sStr )=0; + virtual std::string getAsString()=0; + + ConfPairBase &operator=( const std::string &s ); + +private: + +}; + +#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 @@ +#include "conftree.h" + +ConfTree::ConfTree() +{ +} + +ConfTree::~ConfTree() +{ +} 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 @@ +#ifndef CONF_TREE_H +#define CONF_TREE_H + +#include + +/** + * + */ +class ConfTree +{ +public: + ConfTree(); + virtual ~ConfTree(); + +private: + +}; + +#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 @@ +#include "connection.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "exceptions.h" + +// Read buffer size...maybe fix wierd issues... +#define RBS (1024*10) + +Connection::Connection() +{ + nSocket = -1; + bActive = false; + bDisconnectMe = false; + pProtocol = NULL; +} + +Connection::~Connection() +{ + if( pProtocol != NULL ) delete pProtocol; +} + +void Connection::ensureCapacity( int nSize ) +{ + xOutputBuf.ensureCapacity( nSize ); +} + +bool Connection::appendOutput( const char *lpOutput, int nSize ) +{ + return xOutputBuf.appendData( lpOutput, nSize ); +} + +bool Connection::appendOutput( const char lOutput ) +{ + return xOutputBuf.appendData( lOutput ); +} + +bool Connection::appendOutput( const short lOutput ) +{ + return xOutputBuf.appendData( lOutput ); +} + +bool Connection::appendOutput( const int lOutput ) +{ + return xOutputBuf.appendData( lOutput ); +} + +bool Connection::appendOutput( const long lOutput ) +{ + return xOutputBuf.appendData( lOutput ); +} + +bool Connection::appendOutput( const float lOutput ) +{ + return xOutputBuf.appendData( lOutput ); +} + +bool Connection::appendOutput( const double lOutput ) +{ + return xOutputBuf.appendData( lOutput ); +} + +bool Connection::appendOutput( const unsigned char lOutput ) +{ + return xOutputBuf.appendData( lOutput ); +} + +bool Connection::appendOutput( const unsigned short lOutput ) +{ + return xOutputBuf.appendData( lOutput ); +} + +bool Connection::appendOutput( const unsigned long lOutput ) +{ + return xOutputBuf.appendData( lOutput ); +} + +bool Connection::appendOutput( const unsigned int lOutput ) +{ + return xOutputBuf.appendData( lOutput ); +} + +bool Connection::appendInput( const char *lpInput, int nSize ) +{ + return xInputBuf.appendData( lpInput, nSize ); +} + +int Connection::scanInputFor( char cTarget ) +{ + const char *lpTmp = xInputBuf.getData(); + int jMax = xInputBuf.getLength(); + + for( int j = 0; j < jMax; j++ ) + { + if( lpTmp[j] == cTarget ) + { + return j; + } + } + + return -1; +} + +const char *Connection::getOutput() +{ + return xOutputBuf.getData(); +} + +const char *Connection::getInput() +{ + return xInputBuf.getData(); +} + +void Connection::setSocket( int nNewSocket ) +{ + nSocket = nNewSocket; +} + +int Connection::getSocket() +{ + return nSocket; +} + +bool Connection::isActive() +{ + return bActive; +} + +void Connection::close() +{ + //printf("Close called, socket is: %s\n", bActive?"Active":"Inactive" ); + if( bActive ) + { + fsync( nSocket ); + ::close( nSocket ); + //printf("Socket closed.\n"); + } + bActive = false; + //nSocket = -1; + xInputBuf.clearData(); + xOutputBuf.clearData(); + if( pProtocol != NULL ) + { + delete pProtocol; + pProtocol = NULL; + } +} + +bool Connection::open( int nNewSocket ) +{ + bActive = true; + setSocket( nNewSocket ); + bDisconnectMe = false; + + return true; +} + +bool Connection::open( const char *sAddr, int nPort, int nSec ) +{ + struct sockaddr_in xServerName; + bActive = false; + + /* Create the socket. */ + nSocket = socket( PF_INET, SOCK_STREAM, 0 ); + + if( nSocket < 0 ) + { + bActive = false; + return false; + } + + // These lines set the socket to non-blocking, a good thing? + int flags; + flags = fcntl(nSocket, F_GETFL, 0); + flags |= O_NONBLOCK; + if (fcntl(nSocket, F_SETFL, flags) < 0) + { + return false; + } + + /* Connect to the server. */ + //printf("Resolving hostname (%s)...\n", sAddr ); + { + struct hostent *hostinfo; + + xServerName.sin_family = AF_INET; + xServerName.sin_port = htons( nPort ); + hostinfo = gethostbyname( sAddr ); + if (hostinfo == NULL) + { + return false; + } + xServerName.sin_addr = *(struct in_addr *) hostinfo->h_addr; + } + + //printf("Making actual connection..."); + //fflush( stdout ); + connect( + nSocket, + (struct sockaddr *)&xServerName, + sizeof(xServerName) + ); + //printf("Connected.\n"); + + bActive = true; + bDisconnectMe = false; + + if( nSec > 0 ) + { + fd_set rfds, wfds, efds; + int retval; + + FD_ZERO(&rfds); + FD_SET(nSocket, &rfds); + FD_ZERO(&wfds); + FD_SET(nSocket, &wfds); + FD_ZERO(&efds); + FD_SET(nSocket, &efds); + + struct timeval tv; + tv.tv_sec = nSec; + tv.tv_usec = 0; + + retval = select( nSocket+1, &rfds, &wfds, &efds, &tv ); + + if( retval == 0 ) + { + close(); + throw ExceptionBase("Connection timeout.\n"); + } + + } + + /* + if( ret < 0 ) + { + return false; + }*/ + + return true; +} + +int Connection::readInput() +{ + char buffer[RBS]; + int nbytes; + int nTotalRead=0; + + for(;;) + { + //memset( buffer, 0, RBS ); + + nbytes = read( nSocket, buffer, RBS ); + if( nbytes < 0 && errno != 0 && errno != EAGAIN ) + { + //printf("errno: %d, %s\n", errno, strerror( errno ) ); + /* Read error. */ + //perror("readInput"); + throw ConnectionException( excodeReadError, "Read error: %s", strerror( errno ) ); + } + else + { + if( nbytes <= 0 ) + break; + nTotalRead += nbytes; + appendInput( buffer, nbytes ); + /* Data read. */ + if( nbytes < RBS ) + { + break; + } + + /* New test, if data is divisible by RBS bytes on some libs the + * read could block, this keeps it from happening. + */ + { + fd_set rfds; + FD_ZERO(&rfds); + FD_SET(nSocket, &rfds); + struct timeval tv = { 0, 0 }; + int retval = select( nSocket+1, &rfds, NULL, NULL, &tv ); + if( retval == -1 ) + throw ConnectionException( + excodeBadReadError, + "Bad Read error" + ); + if( !FD_ISSET( nSocket, &rfds ) ) + break; + } + + } + } + + if( pProtocol != NULL && nTotalRead > 0 ) + { + pProtocol->onNewData(); + } + + return nTotalRead; +} + +bool Connection::readInput( int nSec, int nUSec, int *pnSecBack, int *pnUSecBack ) +{ + fd_set rfds, efds; + struct timeval tv, start, end; + struct timezone tz; + int retval; + + gettimeofday( &start, &tz ); + + FD_ZERO(&rfds); + FD_SET(nSocket, &rfds); + FD_ZERO(&efds); + FD_SET(nSocket, &efds); + + tv.tv_sec = nSec; + tv.tv_usec = nUSec; + + //printf("Starting at %d %d\n", nSec, nUSec ); + retval = select( nSocket+1, &rfds, NULL, NULL, &tv ); + + if( retval == -1 ) + { + // Oh my god!!! some kind of horrible problem!!!! + throw ConnectionException( excodeBadReadError, "Bad Read error"); + return false; + } + else if( retval ) + { + //printf("retval=%d, nSocket=%d,%d, sec=%d, usec=%d\n", retval, nSocket, FD_ISSET( nSocket, &rfds ), tv.tv_sec, tv.tv_usec ); + // None of them have data, but the connection is still active. + if( FD_ISSET( nSocket, &rfds ) ) + { + if( readInput() == 0 ) + { + throw ConnectionException( excodeConnectionClosed, "Connection closed"); } + } + } + + gettimeofday( &end, &tz ); + + int st, ust; + st = nSec - ( end.tv_sec - start.tv_sec ); + if( ( end.tv_usec - start.tv_usec ) > nUSec ) + { + (st)--; + ust = 1000000 - (end.tv_usec - start.tv_usec); + } + else + { + ust = nUSec - (end.tv_usec - start.tv_usec); + } + + if( st < 0 ) + { + st = ust = 0; + } + + if( pnSecBack ) + { + *pnSecBack = st; + *pnUSecBack = ust; + } + + //printf("New time: %d %d\n", *pnSecBack, *pnUSecBack ); + + return true; +} + +void Connection::waitForInput( int nBytesIn, int nSec, int nUSec ) +{ + int rlen = getInputAmnt(); + + if( rlen >= nBytesIn ) + return; + + while( rlen < nBytesIn ) + { + if( nSec == 0 && nUSec == 0 ) + { + throw ConnectionException( excodeSocketTimeout, "Timed out while waiting for %d bytes.", nBytesIn ); + } + readInput( nSec, nUSec, &nSec, &nUSec ); + rlen = getInputAmnt(); + } +} + +bool Connection::clearOutput() +{ + return xOutputBuf.clearData(); +} + +bool Connection::clearInput() +{ + return xInputBuf.clearData(); +} + +#define min( a, b ) ((asetConnection( this ); +} + +int Connection::getInputAmnt() +{ + return xInputBuf.getLength(); +} + +int Connection::getOutputAmnt() +{ + return xOutputBuf.getLength(); +} + +class Protocol *Connection::getProtocol() +{ + return pProtocol; +} + +void Connection::printInputDebug( const char *lpPrefix, FILE *fh, int nBytesMax ) +{ + printDataDebug( + (const unsigned char *)xInputBuf.getData(), + xInputBuf.getLength(), + "input", + lpPrefix, + fh, + nBytesMax + ); +} + +void Connection::printOutputDebug( const char *lpPrefix, FILE *fh, int nBytesMax ) +{ + printDataDebug( + (const unsigned char *)xOutputBuf.getData(), + xOutputBuf.getLength(), + "output", + lpPrefix, + fh, + nBytesMax + ); +} + +void Connection::printDataDebug( const unsigned char *pData, long nDataLen, const char *lpName, const char *lpPrefix, FILE *fh, int nBytesMax ) +{ + if( nBytesMax > 0 ) + { + nDataLen = (nBytesMax32 && pData[j+k]<=128)?(pData[j+k]):('.') ); + } + fprintf( fh, "\n"); + j += kmax; + if( j >= nDataLen ) break; + } + fprintf( fh, lpPrefix ); + for( int l = 0; l < 8*3+2*8+2; l++ ) fprintf( fh, (l!=8*3)?("-"):("+") ); fprintf( fh, "\n"); +} + 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 @@ +/**\file + * Contains the Connection class. + *@author Mike Buland + */ + +#ifndef CONNECTION_H +#define CONNECTION_H + +#include "multilog.h" +#include "flexbuf.h" +#include "protocol.h" + +/** Represents a single connection on a network. While these connections + * may be treated more or less just like files, occasionally problems arise + * when writing data at any time you feel like. Therefore you run all your + * data through a Connection, which buffers all data and makes sure no + * buffers are exceeded and nothing inappropriate for the recipient of the + * data is sent. + *@author Mike Buland + */ +class Connection +{ +public: + /** + * Construct a blank and non-connected Connection. The created object is + * not yet connected to anything, and most of the functions except open are + * unusable. + */ + Connection(); + + /** + * Destroy the connection, clean up all pending data requests and close the + * contained socket. This does not send out pending data, especially since + * such an operation could take considerable time, depending on the pending + * data and state of the receiving end. + */ + virtual ~Connection(); + + /** + * Open a connection to a remote server. This sets up this connection as + * a client instead of a server and does all of the work that needs to be + * done to actually open an INET_AF connection, which is a lot of work. + *@param sAddr The address to connect to. This can be in any format + * normally understood by your system to be an address, ip, domain name, + * etc. + *@param nPort The port number to connect to on the remote server. + *@returns True if the connection was successful and everything is setup, + * false if there were any of a dozen errors and the connection is not set. + *@todo Make this function add log entries to a standard MultiLog if + * something goes wrong. + */ + bool open( const char *sAddr, int nPort, int nSec=30 ); + + void ensureCapacity( int nSize ); + + /** Append the given data to the output. The data is presumed to be null + * terminated. To put binary data into the stream, use the other + * appendOutput function. This should be the only method used to + * communicate with the socket. + *@param lpOutput The data to add to the output queue. + *@param nSize How much data is in the lpOutput buffer. If this value + * is -1 then the program treats lpOutput as a null-terminated string. + *@returns True if everything is ok, false otherwise. + */ + bool appendOutput( const char *lpOutput, int nSize=-1 ); + + /** + * Append the character to the output. + *@param lOutput The character to add to the output queue. + *@returns True if everything is ok, false otherwise. + */ + bool appendOutput( const char lOutput ); + + /** + * Append the short to the output. + *@param lOutput The short to add to the output queue. + *@returns True if everything is ok, false otherwise. + */ + bool appendOutput( const short lOutput ); + + /** + * Append the int to the output. + *@param lOutput The int to add to the output queue. + *@returns True if everything is ok, false otherwise. + */ + bool appendOutput( const int lOutput ); + + /** + * Append the long to the output. + *@param lOutput The long to add to the output queue. + *@returns True if everything is ok, false otherwise. + */ + bool appendOutput( const long lOutput ); + + /** + * Append the float to the output. + *@param lOutput The float to add to the output queue. + *@returns True if everything is ok, false otherwise. + */ + bool appendOutput( const float lOutput ); + + /** + * Append the double to the output. + *@param lOutput The double to add to the output queue. + *@returns True if everything is ok, false otherwise. + */ + bool appendOutput( const double lOutput ); + + /** + * Append the unsigned char to the output. + *@param lOutput The unsigned char to add to the output queue. + *@returns True if everything is ok, false otherwise. + */ + bool appendOutput( const unsigned char lOutput ); + + /** + * Append the unsigned short to the output. + *@param lOutput The unsigned short to add to the output queue. + *@returns True if everything is ok, false otherwise. + */ + bool appendOutput( const unsigned short lOutput ); + + /** + * Append the unsigned int to the output. + *@param lOutput The unsigned int to add to the output queue. + *@returns True if everything is ok, false otherwise. + */ + bool appendOutput( const unsigned int lOutput ); + + /** + * Append the unsigned long to the output. + *@param lOutput The unsigned long to add to the output queue. + *@returns True if everything is ok, false otherwise. + */ + bool appendOutput( const unsigned long lOutput ); + + /** + * Writes all input data in the buffer in a dual-view ascii and hex display + * to a file. There are a number of options that also help with debugging. + *@param lpPrefix Text to be added to the begining of every line written + * out. The default is a blank string. + *@param fh The file to write the data to in text mode. This is stdout by + * default, but could be any already open file handle. + *@param nBytesMax The maximum number of bytes to write to the output. The + * amount of data can be overwhelming sometimes, so you can limit it. The + * default value is -1, which is also unlimited. + */ + void printInputDebug( const char *lpPrefix="", FILE *fh=stdout, int nBytesMax=-1 ); + + /** + * Writes all output data in the buffer in a dual-view ascii and hex display + * to a file. There are a number of options that also help with debugging. + *@param lpPrefix Text to be added to the begining of every line written + * out. The default is a blank string. + *@param fh The file to write the data to in text mode. This is stdout by + * default, but could be any already open file handle. + *@param nBytesMax The maximum number of bytes to write to the output. The + * amount of data can be overwhelming sometimes, so you can limit it. The + * default value is -1, which is also unlimited. + */ + void printOutputDebug( const char *lpPrefix="", FILE *fh=stdout, int nBytesMax=-1 ); + + /** + * This is the low-level generic function that is called by both + * printInputDebug and printOutputDebug. It works effectively just like + * both of them, except that you can give it a raw pointer to the data to + * print out. This probably doesn't belong in this class, but this was + * where I was when I needed it. + *@param pData A pointer to the data to write. This is not treated as a + * null terminated string, so make sure that the nDataLen param is set + * properly. + *@param nDataLen The number of bytes that are in pData and that you want to + * see. + *@param lpName The name of the data, this is used in the header where it + * says "Displaying nnn bytes of ." A good example would be input + * or output. + *@param lpPrefix Text to put before every line output. This just makes it + * easier to tell large blocks apart in the output. + *@param fh The file handle to write all data to. + *@param nBytesMax The maximum number of bytes. This parameter is stupid. + * If it is set to -1, then nDataLen is used, otherwise the smaller value is + * used as the number of bytes to output. + *@todo Put this function somewhere more deserving. + *@todo Remove the nBytesMax param, we need that in the other functions, + * not this one! + */ + void printDataDebug( const unsigned char *pData, long nDataLen, const char *lpName, const char *lpPrefix, FILE *fh, int nBytesMax ); + + /** Append the given data to the input. The data is presumed to be null + * terminated. To put binary data into the stream, use the other + * appendInput function. This is mainly used by internal routines. + *@param lpInput The data to add to the input queue. + *@param nSize How much data is in the lpInput buffer. If this value + * is -1 then the program treats lpOutput as a null-terminated string. + *@returns True if everything is ok, false otherwise. + */ + bool appendInput( const char *lpInput, int nSize=-1 ); + + /** Searches through the current pending input for a certain character. + * This is useful for finding out where exactly the end of a line is, for + * example, to see if a command has been entered yet. + *@param cTarget The character to search for. + *@returns The position of the target relative to the begining of the input + * or -1 if the target wasn't found. + */ + int scanInputFor( char cTarget ); + + /** Gets a pointer to the output buffer. This is mainly used by internal + * routines, and is cleared every click when data is sent out again. + *@returns A pointer to the buffer holding the pending output data. + */ + const char *getOutput(); + + /** Gets a pointer to the start of the input buffer's active data + * section. Use this to gain access to the input you need to do + * your job. + *@returns A pointer to the data in the input buffer. Do not delete this. + */ + const char *getInput(); + + /** Clears all pending output, this is mainly just used internally. + *@returns True if operation was a success, otherwise false. + */ + bool clearOutput(); + + /** Clears all pending input, weather it's been used or not. Please + * refrain from calling this during normal operation, use usedInput + * instead, it's much safer. + *@returns True if the operation was a success, false otherwise. + */ + bool clearInput(); + + /** Sets the socket that should be used internally. + *@param nNewSocket The new socket to work with. + */ + void setSocket( int nNewSocket ); + + /** Gets the handle (number) of the working socket. This can be a + * dangerous function to call, please refrain from calling it directly + * if any alternative can be found. + *@returns The number of the working socket. + */ + int getSocket(); + + /** Determines if the connection is still active. + *@returns True if the connection is active, false otherwise. + */ + bool isActive(); + + /** Clears all buffers and sets up the connection to be reused. + * Does not actually close the socket, that's handled by the + * ConnectionManager + */ + void close(); + + /** Opens a socket. Really just sets up the connection for use since + * the socket itself was created and opened by the ConnectionManager. + * This also calls setSocket so you don't have to. + *@param nNewSocket The socket to assosiate with. + */ + bool open( int nNewSocket ); + + /** + * Reads all pending input from the connection. If this is called outside + * of the ConnectionManager it will usually block indefinately waiting for + * new data. The only way to change this behaviour is to modify the socket + * low-level when you connect it manually, or, preferably use the other + * readInput function to control blocking time. + *@returns True socket is still connected, otherwise false. + */ + int readInput(); + + /** + * Reads all pending input from the connection, blocking up to nSec + * seconds and nUSec micro-seconds for the data. This uses select to + * simulate blocking, but has the same effect as standard io blocking. + * If you don't want to block, just set both values to zero. The back + * parameters are optional, set to null to not use them. The variables + * you pass in through the back parameters will contain the remaining + * time if data arrived before the max timeout was reached. + *@param nSec Max seconds to wait. + *@param nUSec Max micro-seconds to wait. + *@param pnSecBack The number of seconds remaining. + *@param pnUSecBack The number of micro-seconds remaining. + */ + bool readInput( int nSec, int nUSec, int *pnSecBack=NULL, int *pnUSecBack=NULL ); + + /** + * Waits until at least nBytesIn are read into the input buffer and ready + * to be used. Wait at most nSec seconds plus nUSec micro seconds. + * If the timeout is exceeded, this function throws an exception. If this + * function returns normally, you are guranteed to have at least nBytesIn + * bytes in your input buffer. + *@param nBytesIn Number of bytes to read. + *@param nSec The max seconds to wait. + *@param sUSec The max microseconds to wait. + */ + void waitForInput( int nBytesIn, int nSec, int nUSec ); + + /** Writes some data that is pending to the socket. + *@returns True if all data was written succesfully, false otherwise. + */ + bool writeOutput(); + + /** + * Writes all data that is pending on the socekt. + */ + bool writeAllOutput(); + + /** Determines if the connection has output waiting to go out. + *@returns true if there is pending output, otherwise false. + */ + bool hasOutput(); + + /** Sets internal flags so that this connection will be deleted next + * time through the ConnectionManager. + */ + void disconnect(); + + /** Determines if this connection is ready to be disconnected or not. + *@returns True if it is time to disconnect, false if it isn't. + */ + bool needDisconnect(); + + /** Tells the caller if there is pending input waiting to be processed. + *@returns True if there is pending input that has not been used, returns + * false if there isn't. + */ + bool hasInput(); + + /** Removes bytes from the begining of the input queue. Use this after + * getting the input and processing as much as you need to. + *@param nAmount The number of bytes used. + *@returns true if the update was successful, otherwise false. + */ + bool usedInput( int nAmount ); + + /** Sets the protocol to be used by this connection. All data in and out + * passes through the protocol object, which may process that data to + * filter out and process any special messages that may have been + * included. Everything that isn't processed can be accessed in the + * standard method. + *@param pNewProtocol A pointer to a protocol object that you want to + * use. + */ + void setProtocol( class Protocol *pNewProtocol ); + + /** Gets the number of bytes that are waiting in the input queue, the data + * that has yet to be processed. + *@returns The number of bytes in the input queue. + */ + int getInputAmnt(); + + /** Gets the number of bytes that are waiting in the output queue, the data + * that has yet to be sent to the connected socket. + *@returns The number of bytes in the input queue. + */ + int getOutputAmnt(); + + /** Gets a pointer to the protocol that is attatched to this connection + * object. This is useful to set modes, and send special commands in + * addition to the standard raw data reads and writes that are normally + * permitted. In fact, in everything besides a raw telnet protocol all + * data should be sent through the protocol and not the connection object. + *@returns A pointer to the Protocol assosiated with this connection. + */ + class Protocol *getProtocol(); + +private: + /** + * A buffer to keep data read from the socket in. This is filled in by + * the function readInput, which is automatically called by the + * ConnectionManager whenever new data is ready. + */ + FlexBuf xInputBuf; + + /** + * A buffer to keep data that should be sent to the socket. This is filled + * in by using the AppendOutput functions and is sent to the socket using + * the writeOutput function, which is automatically called every cycle by + * the ConnectionManager when there is pending data. + */ + FlexBuf xOutputBuf; + + /** + * The socket that the user is connected to. This is not the same as the + * socket number of the listening socket, this is the unique socket on the + * system that the data is coming to. + */ + int nSocket; + + /** + * True=active connection, False=connection lost + */ + bool bActive; + + /** + * True=disconnect next cycle (after data is transmitted), Flse=keep going. + */ + bool bDisconnectMe; + + /** + * A pointer to a protocol handler that can automatically process the data + * in the buffers. This is optional if you use the connections on your own + * but reccomended if you use this with the rest of the ConnectionManager + * system. + */ + class Protocol *pProtocol; +}; + +#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 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "connectionmanager.h" +#include + +ConnectionManager::ConnectionManager( int nInitPool ) : + xLog( MultiLog::getInstance() ) +{ + //nMasterSocket = -1; + pMonitor = NULL; + for( int j = 0; j < nInitPool; j++ ) + { + lInactive.insert( lInactive.begin(), new Connection() ); + } + FD_ZERO (&fdActive); + FD_ZERO (&fdRead); + FD_ZERO (&fdWrite); + FD_ZERO (&fdException); +} + +ConnectionManager::~ConnectionManager() +{ + std::list::const_iterator i; + for( i = lActive.begin(); i != lActive.end(); i++ ) + { + delete (*i); + } + for( i = lInactive.begin(); i != lInactive.end(); i++ ) + { + delete (*i); + } +} + +bool ConnectionManager::startServer( int nPort ) +{ + /* Create the socket and set it up to accept connections. */ + struct sockaddr_in name; + + /* Give the socket a name. */ + name.sin_family = AF_INET; + name.sin_port = htons( nPort ); + + // I think this specifies who we will accept connections from, + // a good thing to make configurable later on + name.sin_addr.s_addr = htonl( INADDR_ANY ); + + return startServer( name ); +} + +bool ConnectionManager::startServer( const char *sAddr, int nPort ) +{ + /* Create the socket and set it up to accept connections. */ + struct sockaddr_in name; + + /* Give the socket a name. */ + name.sin_family = AF_INET; + name.sin_port = htons( nPort ); + + inet_aton( sAddr, &name.sin_addr ); + + return startServer( name ); +} + +bool ConnectionManager::startServer( struct sockaddr_in &name ) +{ + /* Create the socket. */ + int nMasterSocket = socket (PF_INET, SOCK_STREAM, 0); + if (nMasterSocket < 0) + { + xLog.LineLog( MultiLog::LError, "Couldn't create a listen socket."); + return false; + } + + int opt = 1; + setsockopt( + nMasterSocket, + SOL_SOCKET, + SO_REUSEADDR, + (char *)&opt, + sizeof(opt) + ); + + if (bind (nMasterSocket, (struct sockaddr *) &name, sizeof (name)) < 0) + { + xLog.LineLog( MultiLog::LError, "Couldn't bind to the listen socket."); + return false; + } + + if (listen (nMasterSocket, 40) < 0) + { + xLog.LineLog( MultiLog::LError, "Couldn't begin listening to the server socket."); + return false; + } + + /* Initialize the set of active sockets. */ + FD_SET (nMasterSocket, &fdActive); + + sMasterSocket[nMasterSocket] = name.sin_port; + + return true; +} + +bool ConnectionManager::startServer( int nPort, int nNumTries, int nTimeout ) +{ + struct timeval xTimeout; + + for( int j = 0; j < nNumTries; j++ ) + { + xLog.LineLog( MultiLog::LStatus, "Attempting to create server socket (attempt [%d/%d])...", j+1, nNumTries ); + if( startServer( nPort ) == true ) + { + return true; + } + else if( j < nNumTries-1 ) + { + xLog.LineLog( MultiLog::LStatus, "Waiting for %d secconds to allow port to clear...", nTimeout ); + xTimeout.tv_sec = nTimeout; + xTimeout.tv_usec = 0; + if (select(0, (fd_set *) 0, (fd_set *) 0, (fd_set *) 0, &xTimeout) < 0) { + xLog.LineLog( MultiLog::LError, "Error using select to sleep for a while."); + } + usleep( nTimeout ); + } + } + + return false; +} + +bool ConnectionManager::scanConnections( int nTimeout, bool bForceTimeout ) +{ + struct timeval xTimeout; + + xTimeout.tv_sec = nTimeout / 1000000; + xTimeout.tv_usec = nTimeout % 1000000; + + /* Block until input arrives on one or more active sockets. */ + fdRead = fdActive; + fdWrite = fdActive; + fdException = fdActive; + + // We removed the write checking because it just checks to see if you *can* + // write...that's stupid, they're all open, so it always exits immediately + // if there are ANY connections there... + if( TEMP_FAILURE_RETRY( select( FD_SETSIZE, &fdRead, (fd_set *)0/*&fdWrite*/, &fdException, &xTimeout ) ) < 0 ) + { + xLog.LineLog( MultiLog::LError, "Error attempting to scan open connections."); + perror("ConnectionManager"); + return false; + } + // Now we use select to sleep as well as to scan for connections, now we + // just need to fix the fact that if there are no connections, the seccond + // select call doesn't return until there is a connection... + if( bForceTimeout ) + { + if (select(0, (fd_set *) 0, (fd_set *) 0, (fd_set *) 0, &xTimeout) < 0) { + xLog.LineLog( MultiLog::LError, "Error using select to sleep for a while."); + } + } + + /* Service all the sockets with input pending. */ + for( int i = 0; i < FD_SETSIZE; ++i ) + { + if( FD_ISSET( i, &fdRead ) ) + { + if( sMasterSocket.find( i ) != sMasterSocket.end() ) + { + addConnection( i ); + } + else + { + Connection *pCon = findActiveConnection( i ); + if( pCon == NULL ) + { + xLog.LineLog( MultiLog::LError, "A connection object was lost, or never created!"); + return false; + } + + /* Data arriving on an already-connected socket. */ + if( pCon->readInput() == 0 ) + { + xLog.LineLog( MultiLog::LStatus, "Closing connection due to disconnect."); + close( i ); + FD_CLR( i, &fdActive ); + pMonitor->onClosedConnection( pCon ); + pCon->close(); + } + else + { + // We actually read something...but the connection handles + // protocol notification, so we don't need to do anything + // here... + } + } + } + } + std::list::iterator i; + for( i = lActive.begin(); i != lActive.end(); i++ ) + { + if( (*i)->isActive() == false ) + { + std::list::iterator l = i; + i--; + lInactive.insert( lInactive.end(), *l ); + lActive.erase( l ); + continue; + } + (*i)->getProtocol()->poll(); + if( (*i)->hasOutput() ) + { + (*i)->writeOutput(); + } + if( (*i)->needDisconnect() && !(*i)->hasOutput() ) + { + int prt = (*i)->getSocket(); + close( prt ); + FD_CLR( prt, &fdActive ); + pMonitor->onClosedConnection( *i ); + (*i)->close(); + lInactive.insert( lInactive.end(), *i ); + std::list::iterator l = i; + i--; + lActive.erase( l ); + xLog.LineLog( MultiLog::LStatus, "Closing connection due to server request."); + } + } + + return true; +} + +bool ConnectionManager::shutdownServer() +{ + while( !lActive.empty() ) + { + Connection *i = *(lActive.begin()); + if( i->isActive() ) + { + pMonitor->onClosedConnection( i ); + i->close(); + lInactive.insert( lInactive.end(), i ); + lActive.erase( lActive.begin() ); + } + } +/* + for( int i = 0; i < nPoolSize; i++ ) + { + + int prt = axConPool[i].getSocket(); + close( prt ); +// FD_CLR( prt, &fdActive ); + pMonitor->onClosedConnection( &axConPool[i] ); + axConPool[i].close(); + } +*/ + std::map::iterator i; + for( i = sMasterSocket.begin(); i != sMasterSocket.end(); i++ ) + { + int nSocket = (*i).first; + shutdown( nSocket, SHUT_RDWR ); + close( nSocket ); + } + + return true; +} + +bool ConnectionManager::broadcastMessage( const char *lpData, int nExcludeSocket ) +{ + std::list::const_iterator i; + for( i = lActive.begin(); i != lActive.end(); i++ ) + { + if( (*i)->isActive() && + (*i)->getSocket() != nExcludeSocket ) + { + (*i)->appendOutput( lpData ); + } + } + + return true; +} + +bool ConnectionManager::addConnection( int nSocket ) +{ + struct sockaddr_in clientname; + size_t size; + int newSocket; + + size = sizeof( clientname ); +#ifdef __CYGWIN__ + newSocket = accept( nSocket, (struct sockaddr *) &clientname, (int *)&size ); +#else + newSocket = accept( nSocket, (struct sockaddr *) &clientname, &size ); +#endif + if( newSocket < 0 ) + { + xLog.LineLog( MultiLog::LError, "Error accepting a new connection!" ); + return false; + } +// char *tmpa = inet_ntoa(clientname.sin_addr); + char tmpa[20]; + inet_ntop( AF_INET, (void *)&clientname.sin_addr, tmpa, 20 ); + xLog.LineLog( MultiLog::LStatus, "New connection from host %s, port %hd.", tmpa, ntohs (clientname.sin_port) ); +/* + int nCnt = 0; + for( int j = 0; j < nPoolSize; j++ ) + { + if( axConPool[j].isActive() ) + { + nCnt++; + } + } + xLog.LineLog( MultiLog::LStatus, "Connections %d/%d.", nCnt, nPoolSize ); + */ +// free( tmpa ); + FD_SET( newSocket, &fdActive ); + + //void nonblock(socket_t s) + { + int flags; + + flags = fcntl(newSocket, F_GETFL, 0); + flags |= O_NONBLOCK; + if (fcntl(newSocket, F_SETFL, flags) < 0) + { + return false; + } + } + + Connection *pCon = getInactiveConnection(); + pCon->open( newSocket ); + + pMonitor->onNewConnection( pCon, (*sMasterSocket.find(nSocket)).second ); + if( pCon->getProtocol() ) + pCon->getProtocol()->onNewConnection(); + + lActive.insert( lActive.end(), pCon ); + + return true; +} + +void ConnectionManager::connect( + const char *lpAddress, + int nPort, + int nProtocolPort, + Protocol *pNewProto + ) +{ + Connection *pCon = getInactiveConnection(); + pCon->open( lpAddress, nPort ); + int nSocket = pCon->getSocket(); + FD_SET( nSocket, &fdActive ); + + pCon->setProtocol( pNewProto ); + pMonitor->onNewClientConnection( pCon, nProtocolPort ); + if( pCon->getProtocol() ) + pCon->getProtocol()->onNewClientConnection(); + + lActive.insert( lActive.end(), pCon ); +} + +Connection *ConnectionManager::getInactiveConnection() +{ + if( lInactive.empty() ) + { + return new Connection(); + } + Connection *pCon = *(lInactive.begin()); + lInactive.erase( lInactive.begin() ); + return pCon; +} + +Connection *ConnectionManager::findActiveConnection( int nSocket ) +{ + std::list::const_iterator i; + for( i = lActive.begin(); i != lActive.end(); i++ ) + { + if( (*i)->getSocket() == nSocket ) + { + return *i; + } + } + + return NULL; +} + +void ConnectionManager::setConnectionMonitor( ConnectionMonitor *pNewMonitor ) +{ + pMonitor = pNewMonitor; +} 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 @@ +/** + *@file + * Contains the ConnectionManager. + *@author Mike Buland + */ + +#ifndef CONNECTIONMANAGER_H +#define CONNECTIONMANAGER_H + +#include "multilog.h" +#include "connection.h" +#include "connectionmonitor.h" +#include +#include +#include + +/** Manges incoming network connections as a server. Creates and works with + * Connection objects. All operations are performed on TCP/IP v4 right now, + * and on a single port, although any number of connections can be handled. + *@author Mike Buland + */ +class ConnectionManager +{ +public: + /** + * Sets up the basics, like storage for the pool, and so on. This does not + * actually start a server, bind to a port, or create a connection pool. + * That's all handled by startServer(). + */ + ConnectionManager( int nInitPool=40 ); + + /** + * Cleans up everything, and even clears out all still-connected Connection + * objects. + */ + virtual ~ConnectionManager(); + + /** + * Starts a server socket and binds to it, listening for new connections. + * Unlike the version of this that takes two parameters, this listens on + * all local addresses, or the virtual 0.0.0.0 address if available, which + * is mapped to all active local addresses. + *@param nPort The port to listen on. + *@returns True if the socket was bound to the port and serving was + * started. False if there was a problem connecting to the port. + */ + bool startServer( int nPort ); + + /** + * Starts a server socket and binds to it, listening only on the address + * specified. If you want to listen to all local addresses you can enter + * "0.0.0.0" for the address, but the version of this with one parameter + * is more universal. + *@param sAddr The local ip address to bind to + *@param nPort The port to listen on. + *@returns True if the socket was bound to the port and serving was + * started. False if there was a problem connecting to the port. + */ + bool startServer( const char *sAddr, int nPort ); + + /** + * I recomend probably not using this function on your own too much, it + * does the real work of setting up a socket, but requires a properly + * prepared sackaddr_in structure. This isn't too hard, but it's easier + * to use the other startServer functions. They call this function after + * some prepwork. + *@param name A properly formed sockaddr_in structure that will not be + * modified, but describes how to listen and to what to listen. + *@returns True on success. + */ + bool startServer( struct sockaddr_in &name ); + + /** + * This is identicle to the simpler startServer function except that it + * will automatically try to connect multiple times in case the first + * attempt or two doesn't work for some reason. Initially this was + * written to compensate for server sockets staying locked after they were + * closed for a while. + *@param nPort The port to listen on. + *@param nInitPool The size of the initial connection pool. This will + * grow automatically if necesarry. + *@param nNumTries The maximum number of times to try to connect. + *@param nTimeout The amount of time to wait in-between connection + * attempts. + *@returns True if the socket was bound to the port and serving was + * started. False if there was a problem connecting to the port. + */ + bool startServer( int nPort, int nNumTries, int nTimeout ); + + /** + * Scans all open connections, halting the calling processes until data + * is received or nTimeout ms have gone by. While waiting for the timeout + * to complete the process is placed into an idle mode. + *@param nTimeout The number of millisecconds to wait if there is nothing + * to actually do. + *@param bForceTimeout If set to true, this will force the scanner to wait + * for the timout to complete before returning, even if there was pending + * data. + */ + bool scanConnections( int nTimeout, bool bForceTimeout ); + + /** Shutdown the server and all assosiated sockets. + *@returns True if every socket was closed without problem. + */ + bool shutdownServer(); + + /** Sends a message directly to every connected port. + *@param lpData A null-terminated string of data to send. + *@param nExcludeSocket An optional socket to exclude from the broadcast. + *@returns True if every socket that should have gotten the message did. + */ + bool broadcastMessage( const char *lpData, int nExcludeSocket=-1 ); + + /** Sets a monitor for the manager. The monitor is sent notifications + * whenever a socket is connected, disconnected, or whenever an error + * occurs. + *@param pNewMonitor A pointer to a preconstructed ConnectionMonitor + */ + void setConnectionMonitor( ConnectionMonitor *pNewMonitor ); + + void connect( const char *lpAddress, int nPort, int nProtocolPort, Protocol *pNewProto ); + +private: + /** + * Take care of the work of actually accepting a connection. This will + * accept the connection, set the initial modes, and add it to the master + * list of active connections, as well as fire off any messages that need + * to be handled by anything else. + *@param nSocket The handle of the listening socket that had an incoming + * connection. + *@returns True if everything worked, False otherwise. + */ + bool addConnection( int nSocket ); + + /** + * Seraches the internal lists of connections for one with a specific + * socket. + *@param nSocket The socket the connection is using for communication. + * This is the unique socket and not the one that the connection was + * initially to. + *@returns NULL if no connection was found, otherwise a pointer to a live + * Connection object. + */ + Connection *findActiveConnection( int nSocket ); + + /** + * Searches the connection pool for an object that isn't in use yet, and + * returns it, ready to be filled in and used. + *@returns An unused connection object ready for use. + *@todo Check this code over to insure that the pool grows appropriately + * when enough extra connections are detected. + */ + Connection *getInactiveConnection(); + + std::map sMasterSocket; + //int nMasterSocket; /**< The listening or server socket. */ + fd_set fdActive; /**< The active socket set. */ + fd_set fdRead; /**< The sockets ready for a read. */ + fd_set fdWrite; /**< The sockets ready for a write. */ + fd_set fdException; /**< The sockets that have gotten errors. */ + std::list lInactive; /**< The pool of inactive Connections */ + std::list lActive; /**< The pool of active Connections */ + MultiLog &xLog; /**< A handle to the active multilog. */ + + /** The ConnectionMonitor to notify of new connections. */ + ConnectionMonitor *pMonitor; +}; + +#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 @@ +#include "connectionmonitor.h" + +ConnectionMonitor::ConnectionMonitor() +{ +} + +ConnectionMonitor::~ConnectionMonitor() +{ +} + 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 @@ +/**@file + * Describes the ConnectionMonitor class. + */ +#ifndef CONNECTIONMONITOR_H +#define CONNECTIONMONITOR_H + +#include "connection.h" + +/** Connection Monitor defines the base class of the objects that will be + * notified whenever a connection is created or destroyed. + *@author Mike Buland + */ +class ConnectionMonitor +{ +public: + /** + * This is only here for completeness. It does nothing. + */ + ConnectionMonitor(); + + /** + * This is only here for completeness. It does nothing. + */ + virtual ~ConnectionMonitor(); + + /** Receives the notification that new connection was received. + *@param pCon The connection that was created. + *@param nSocket The socket that the client connected to, used to determine + * which protocol to apply. + *@returns Should return a true value if everything is OK, a false to + * force a shutdown. + */ + virtual bool onNewConnection( Connection *pCon, int nPort ) = 0; + virtual bool onNewClientConnection( Connection *pCon, int nPort ) + { + return onNewConnection( pCon, nPort ); + }; + + /** Receives the notification that a connection was closed. + *@param pCon The connection that was closed. + *@returns Should return a true value if everything is OK, a false to + * force a shutdown. + */ + virtual bool onClosedConnection( Connection *pCon ) = 0; +}; + +#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 @@ +#include "exceptionbase.h" +#include + +ExceptionBase::ExceptionBase( const char *lpFormat, ... ) throw() : + nErrorCode( 0 ), + sWhat( NULL ) +{ + va_list ap; + + va_start(ap, lpFormat); + setWhat( lpFormat, ap ); + va_end(ap); +} + +ExceptionBase::ExceptionBase( int nCode, const char *lpFormat, ... ) throw() : + nErrorCode( nCode ), + sWhat( NULL ) +{ + va_list ap; + + va_start(ap, lpFormat); + setWhat( lpFormat, ap ); + va_end(ap); +} + +ExceptionBase::ExceptionBase( int nCode ) throw() : + nErrorCode( nCode ), + sWhat( NULL ) +{ +} + +ExceptionBase::~ExceptionBase() throw() +{ + if( sWhat ) + { + delete[] sWhat; + sWhat = NULL; + } +} + +void ExceptionBase::setWhat( const char *lpFormat, va_list &vargs ) +{ + if( sWhat ) delete[] sWhat; + int nSize; + + nSize = vsnprintf( NULL, 0, lpFormat, vargs ); + sWhat = new char[nSize+1]; + vsnprintf( sWhat, nSize+1, lpFormat, vargs ); +} + +void ExceptionBase::setWhat( const char *lpText ) +{ + if( sWhat ) delete[] sWhat; + int nSize; + + nSize = strlen( lpText ); + sWhat = new char[nSize+1]; + strcpy( sWhat, lpText ); +} + +const char *ExceptionBase::what() const throw() +{ + return sWhat; +} + +int ExceptionBase::getErrorCode() +{ + return nErrorCode; +} + 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 @@ +#ifndef EXCEPTION_BASE_H +#define EXCEPTION_BASE_H + +#include +#include +#include + +/** + * A generalized Exception base class. This is nice for making general and + * flexible child classes that can create new error code classes. + */ +class ExceptionBase : public std::exception +{ +public: + /** + * Construct an exception with an error code of zero, but with a + * description. The use of this is not reccomended most of the time, it's + * generally best to include an error code with the exception so your + * program can handle the exception in a better way. + * @param sFormat The format of the text. See printf for more info. + */ + ExceptionBase( const char *sFormat, ... ) throw(); + + /** + * + * @param nCode + * @param sFormat + */ + ExceptionBase( int nCode, const char *sFormat, ... ) throw(); + + /** + * + * @param nCode + * @return + */ + ExceptionBase( int nCode=0 ) throw(); + + /** + * + * @return + */ + virtual ~ExceptionBase() throw(); + + /** + * + * @return + */ + virtual const char *what() const throw(); + + /** + * + * @return + */ + int getErrorCode(); + + /** + * + * @param lpFormat + * @param vargs + */ + void setWhat( const char *lpFormat, va_list &vargs ); + + /** + * + * @param lpText + */ + void setWhat( const char *lpText ); + +private: + int nErrorCode; /**< The code for the error that occured. */ + char *sWhat; /**< The text string telling people what went wrong. */ +}; + +#define subExceptionDecl( name ) \ +class name : public ExceptionBase \ +{ \ + public: \ + name( const char *sFormat, ... ) throw (); \ + name( int nCode, const char *sFormat, ... ) throw(); \ + name( int nCode=0 ) throw (); \ +}; + +#define subExceptionDef( name ) \ +name::name( const char *lpFormat, ... ) throw() : \ + ExceptionBase( 0 ) \ +{ \ + va_list ap; \ + va_start( ap, lpFormat ); \ + setWhat( lpFormat, ap ); \ + va_end( ap ); \ +} \ +name::name( int nCode, const char *lpFormat, ... ) throw() : \ + ExceptionBase( nCode ) \ +{ \ + va_list ap; \ + va_start( ap, lpFormat ); \ + setWhat( lpFormat, ap ); \ + va_end( ap ); \ +} \ +name::name( int nCode ) throw() : \ + ExceptionBase( nCode ) \ +{ \ +} + +#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 @@ +#include "exceptions.h" +#include + +subExceptionDef( XmlException ) +subExceptionDef( FileException ) +subExceptionDef( ConnectionException ) +subExceptionDef( PluginException ) + 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 @@ +#ifndef EXCEPTIONS_H +#define EXCEPTIONS_H + +#include "exceptionbase.h" +#include + +subExceptionDecl( XmlException ) +subExceptionDecl( FileException ) +subExceptionDecl( ConnectionException ) +subExceptionDecl( PluginException ) + +enum eFileException +{ + excodeEOF +}; + +enum eConnectionException +{ + excodeReadError, + excodeBadReadError, + excodeConnectionClosed, + excodeSocketTimeout +}; + +#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 @@ +#include "flexbuf.h" +#include + +FlexBuf::FlexBuf() +{ + lpBuf = new char[1024]; + nLastChar = 0; + nFirstChar = 0; + nSize = 1024; + nFill = 0; + clearData(); +} + +FlexBuf::~FlexBuf() +{ + delete[] lpBuf; +} + +bool FlexBuf::appendData( const char *lpData, int nDSize ) +{ + int nStrLen; + if( nDSize < 0 ) + { + nStrLen = strlen( lpData ); + } + else + { + nStrLen = nDSize; + } + + if( nLastChar + nStrLen + 1 > nSize ) + { + if( nFill + nStrLen + 1 < nSize ) + { + memcpy( lpBuf, lpBuf+nFirstChar, nFill ); + nLastChar -= nFirstChar; + nFirstChar = 0; + } + else + { + nSize += nStrLen+1; + char *lpNewBuf = new char[nSize]; + memcpy( lpNewBuf, lpBuf+nFirstChar, nFill ); + delete[] lpBuf; + lpBuf = lpNewBuf; + nLastChar -= nFirstChar; + nFirstChar = 0; + } + } + + memcpy( &lpBuf[nLastChar], lpData, nStrLen ); + nLastChar += nStrLen; + nFill += nStrLen; + lpBuf[nLastChar] = '\0'; + + return true; +} + +bool FlexBuf::appendData( const char lData ) +{ + if( nLastChar + 2 > nSize ) + { + if( nFill+2 < nSize ) + { + memcpy( lpBuf, lpBuf+nFirstChar, nFill ); + nLastChar -= nFirstChar; + nFirstChar = 0; + } + else + { + nSize += 1024; + char *lpNewBuf = new char[nSize]; + memcpy( lpNewBuf, lpBuf+nFirstChar, nFill ); + delete[] lpBuf; + lpBuf = lpNewBuf; + nLastChar -= nFirstChar; + nFirstChar = 0; + } + } + + lpBuf[nLastChar] = lData; + nLastChar++; + nFill++; + lpBuf[nLastChar] = '\0'; + + return true; +} + +bool FlexBuf::appendData( const short lData ) +{ + return appendData( (const char *)&lData, sizeof(short) ); +} + +bool FlexBuf::appendData( const int lData ) +{ + return appendData( (const char *)&lData, sizeof(int) ); +} + +bool FlexBuf::appendData( const long lData ) +{ + return appendData( (const char *)&lData, sizeof(long) ); +} + +bool FlexBuf::appendData( const float lData ) +{ + return appendData( (const char *)&lData, sizeof(float) ); +} + +bool FlexBuf::appendData( const double lData ) +{ + return appendData( (const char *)&lData, sizeof(double) ); +} + +bool FlexBuf::appendData( const unsigned char lData ) +{ + return appendData( (const char)lData ); +} + +bool FlexBuf::appendData( const unsigned short lData ) +{ + return appendData( (const char *)&lData, sizeof(short) ); +} + +bool FlexBuf::appendData( const unsigned long lData ) +{ + return appendData( (const char *)&lData, sizeof(long) ); +} + +bool FlexBuf::appendData( const unsigned int lData ) +{ + return appendData( (const char *)&lData, sizeof(int) ); +} + +bool FlexBuf::clearData() +{ + nFirstChar = nLastChar = nFill = 0; + lpBuf[nLastChar] = '\0'; + + return true; +} + +const char *FlexBuf::getData() +{ + return (lpBuf+nFirstChar); +} + +int FlexBuf::getLength() +{ + return nFill; +} + +int FlexBuf::getCapacity() +{ + return nSize; +} + +bool FlexBuf::usedData( int nAmount ) +{ + // Remove from the end if negative + if( nAmount < 0 ) + { + if( nFill+nAmount < 0 ) + { + nFill = nFirstChar = nLastChar = 0; + return true; + } + nLastChar += nAmount; + nFill += nAmount; + return true; + } + if( nAmount > nFill ) + { + nAmount = nSize; +// return false; + } + + //nLastChar -= nAmount; + nFirstChar += nAmount; + nFill -= nAmount; + + if( nFill == 0 ) + { + nFirstChar = nLastChar = 0; + } + + //if( nLastChar > 0 ) + //{ + //memmove( lpBuf, &lpBuf[nAmount], nLastChar ); + //} + + return true; +} + +int FlexBuf::findChar( char cTarget ) +{ + for( int j = nFirstChar; j < nLastChar; j++ ) + { + if( lpBuf[j] == cTarget ) + { + return j; + } + } + + return -1; +} + +void FlexBuf::ensureCapacity( int nAmount ) +{ + if( nLastChar + nAmount + 1 > nSize ) + { + if( nFill + nAmount + 1 < nSize ) + { + memcpy( lpBuf, lpBuf+nFirstChar, nFill ); + nLastChar -= nFirstChar; + nFirstChar = 0; + } + else + { + nSize += nAmount+1; + char *lpNewBuf = new char[nSize]; + memcpy( lpNewBuf, lpBuf+nFirstChar, nFill ); + delete[] lpBuf; + lpBuf = lpNewBuf; + nLastChar -= nFirstChar; + nFirstChar = 0; + } + } +} + 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 @@ +/**\flexbuf.h + * Describes the FlexBuf class. + *@author Mike Buland + */ + +#ifndef FLEXBUF_H +#define FLEXBUF_H + +/** Stores any amount of data, but starts small, growing as necesarry. + * It is optimized to work with stream type situations, with data being + * added to the end while it is being taken from the begning. + *@todo Set this class up to auto-shrink back to a specified sized buffer each + * time it has shrunk below that for enough operations. + *@author Mike Buland + */ +class FlexBuf +{ +public: + /** + * Construct a blank FlexBuf containing about 1k of buffer space. + */ + FlexBuf(); + + /** + * Clean up the FlexBuf, delete all buffers. + */ + virtual ~FlexBuf(); + + /** Appends a whole string of data to the buffer. The string + * must be null terminated. + *@param lpData The data to append to the buffer. + *@param nDSize The size of the data described by lpData. If this + * value is -1 lpData is treated as a null-terminated string. + *@returns True if no problems occured, false otherwise. + */ + bool appendData( const char *lpData, int nDSize=-1 ); + + /** Appends a single character to the end of the buffer. + *@param lData The character to append to the buffer. + *@returns True if no problems occured, false otherwise. + */ + bool appendData( const char lData ); + + /** + * Append the short to the buffer. + *@param lData The short to add to the buffer queue. + *@returns True if everything is ok, false otherwise. + */ + bool appendData( const short lData ); + + /** + * Append the int to the buffer. + *@param lData The int to add to the buffer queue. + *@returns True if everything is ok, false otherwise. + */ + bool appendData( const int lData ); + + /** + * Append the long to the buffer. + *@param lData The long to add to the buffer queue. + *@returns True if everything is ok, false otherwise. + */ + bool appendData( const long lData ); + + /** + * Append the float to the buffer. + *@param lData The float to add to the buffer queue. + *@returns True if everything is ok, false otherwise. + */ + bool appendData( const float lData ); + + /** + * Append the double to the buffer. + *@param lData The double to add to the buffer queue. + *@returns True if everything is ok, false otherwise. + */ + bool appendData( const double lData ); + + /** + * Append the unsigned char to the buffer. + *@param lData The unsigned char to add to the buffer queue. + *@returns True if everything is ok, false otherwise. + */ + bool appendData( const unsigned char lData ); + + /** + * Append the unsigned short to the buffer. + *@param lData The unsigned short to add to the buffer queue. + *@returns True if everything is ok, false otherwise. + */ + bool appendData( const unsigned short lData ); + + /** + * Append the unsigned int to the buffer. + *@param lData The unsigned int to add to the buffer queue. + *@returns True if everything is ok, false otherwise. + */ + bool appendData( const unsigned int lData ); + + /** + * Append the unsigned long to the buffer. + *@param lData The unsigned long to add to the buffer queue. + *@returns True if everything is ok, false otherwise. + */ + bool appendData( const unsigned long lData ); + + /** Removes all pending data from the buffer. + *@returns True if no problems occured, false otherwise. + */ + bool clearData(); + + /** Gets a pointer to the internal buffer, at the begining of the current + * data stream. + *@returns A pointer to the internal data buffer. + */ + const char *getData(); + + /** Gets the length of the current buffer (how much data is really in the + * buffer, not it's current capacity, for that check getCapacity) + *@returns The length of the current buffer. + */ + int getLength(); + + /** Gets the current capacity of the FlexBuf. If the size nears this value + * then the entire buffer is resized to accomidate more data. + *@returns The current capacity of the FlexBuf. + */ + int getCapacity(); + + /** + * Removes nAmount bytes from the begning of the buffer. Actually, if + * nAmount happens to be negative it will remove tha absolute value of + * nValue bytes from the end of the buffer, like the old delData command. + *@param nAmount The number of bytes used. + *@returns True if everything was successful, false if there was an error. + */ + bool usedData( int nAmount ); + + /** Finds the first instance of the given character in the buffer and + * returns an index to it. + *@param cTarget The character you're looking for. + *@returns The index of the first instance of the given character, or + * -1 if it just wasn't found. + */ + int findChar( char cTarget ); + + void ensureCapacity( int nAmount ); + +private: + /** The raw storage location of the FlexBuf. */ + char *lpBuf; + /** The real size of the FlexBuf. */ + int nSize; + /** Where the last char is. */ + int nLastChar; + /** Where the first char is. */ + int nFirstChar; + /** The amount of real data in the FlexBuf. This is effectively nLastChar-nFirstChar. */ + int nFill; +}; + +#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 @@ +#include "formula.h" + +subExceptionDef( ParseException ); + +Formula::Formula() +{ + hVars["pi"] = M_PI; + hVars["e"] = M_E; + + hFunc["sin"] = FuncSin(); +} + +Formula::~Formula() +{ +} + +double Formula::run( char *sFormula ) +{ + for(;;) + { + uint8_t tNum = nextToken( &sFormula ); + if( tNum == symEOS ) + break; + else if( tNum == symSubtract ) + { + tNum = nextToken( &sFormula ); + if( tNum != symNumber ) + throw ParseException("Unary minus must be followed by a number, " + "variable, function, or parenthesis."); + sValue.top() = -sValue.top(); + } + else if( tNum == symOpenParen ) + { + sOper.push( tNum ); + continue; + } + +oppart: uint8_t tOpr = nextToken( &sFormula ); + if( tOpr == symEOS ) + { + //printf("EOS "); + reduce(); + return sValue.top(); + break; + } + if( !sOper.empty() && getPrec( sOper.top() ) > getPrec( tOpr ) ) + { + reduce(); + } + if( tOpr != symCloseParen ) + { + sOper.push( tOpr ); + } + else + { + reduce( true ); + goto oppart; + } + } + return sValue.top(); +} + +void Formula::reduce( bool bCloseParen ) +{ + while( !sOper.empty() ) + { + uint8_t nOpr = sOper.top(); + if( nOpr == symOpenParen ) + { + //printf("Found ( stopping reduction.\n"); + if( bCloseParen == true ) + sOper.pop(); + return; + } + sOper.pop(); + + double dTop = sValue.top(); + sValue.pop(); + + switch( nOpr ) + { + case symAdd: + //printf("%f + %f = %f\n", sValue.top(), dTop, sValue.top()+dTop ); + sValue.top() += dTop; + break; + + case symSubtract: + //printf("%f - %f = %f\n", sValue.top(), dTop, sValue.top()-dTop ); + sValue.top() -= dTop; + break; + + case symMultiply: + //printf("%f * %f = %f\n", sValue.top(), dTop, sValue.top()*dTop ); + sValue.top() *= dTop; + break; + + case symDivide: + //printf("%f / %f = %f\n", sValue.top(), dTop, sValue.top()/dTop ); + sValue.top() /= dTop; + break; + + case symExponent: + //printf("%f ^ %f = %f\n", sValue.top(), dTop, pow(sValue.top(),dTop) ); + sValue.top() = pow( sValue.top(), dTop ); + break; + + case symModulus: + //printf("%f %% %f = %f\n", sValue.top(), dTop, fmod(sValue.top(),dTop) ); + sValue.top() = fmod( sValue.top(), dTop ); + break; + } + } + + if( bCloseParen == true ) + { + throw ParseException("Close-paren found without matching open-paren."); + } +} + +uint8_t Formula::getPrec( uint8_t nOper ) +{ + switch( nOper ) + { + case symNumber: + case symVariable: + case symOpenParen: + case symCloseParen: + return 0; + + case symAdd: + case symSubtract: + return 1; + + case symMultiply: + case symDivide: + case symModulus: + return 2; + + case symExponent: + return 3; + + default: + return 0; + } +} + +uint8_t Formula::nextToken( char **sBuf ) +{ + for(;;) + { + char cbuf = **sBuf; + ++(*sBuf); + switch( cbuf ) + { + case '+': + return symAdd; + + case '-': + return symSubtract; + + case '*': + return symMultiply; + + case '/': + return symDivide; + + case '^': + return symExponent; + + case '%': + return symModulus; + + case '(': + return symOpenParen; + + case ')': + return symCloseParen; + + case ' ': + case '\t': + case '\n': + case '\r': + break; + + case '\0': + return symEOS; + + default: + if( cbuf == '.' || (cbuf >= '0' && cbuf <= '9') ) + { + char num[50]={cbuf}; + int nPos = 1; + bool bDot = false; + + for(;;) + { + cbuf = **sBuf; + if( cbuf == '.' ) + { + if( bDot == false ) + bDot = true; + else + throw ParseException( + "Numbers cannot have more than one " + ". in them." + ); + } + if( cbuf == '.' || (cbuf >= '0' && cbuf <= '9') ) + { + num[nPos++] = cbuf; + } + else + { + num[nPos] = '\0'; + sValue.push( strtod( num, NULL ) ); + return symNumber; + } + ++(*sBuf); + } + } + else if( (cbuf >= 'a' && cbuf <= 'z') || + (cbuf >= 'A' && cbuf <= 'Z') || + (cbuf == '_') ) + { + char tok[50]={cbuf}; + int nPos = 1; + + for(;;) + { + cbuf = **sBuf; + if( (cbuf >= 'a' && cbuf <= 'z') || + (cbuf >= 'A' && cbuf <= 'Z') || + (cbuf >= '0' && cbuf <= '9') || + cbuf == '_' || cbuf == '.' || cbuf == ':' ) + { + tok[nPos++] = cbuf; + } + else + { + tok[nPos] = '\0'; + //printf("Checking variable \"%s\"\n", tok ); + try + { + sValue.push( hVars[tok] ); + return symNumber; + } + catch( HashException &e ) + { + throw ParseException( + "No variable named \"%s\" exists.", + tok + ); + } + } + ++(*sBuf); + } + } + break; + } + } +} + 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 @@ +#ifndef FORMULA_H +#define FORMULA_H + +#include + +#include +#include +#include "sbuffer.h" + +#include "exceptionbase.h" +#include "hash.h" + +subExceptionDecl( ParseException ); + +/** + * Implements a very simple formula parser that allows use of variables and + * custom functions. This is based on a simple calculator-type parser that + * executes as it processes, accounting for operator precedence and grouping. + */ +class Formula +{ +public: + Formula(); + virtual ~Formula(); + + double run( char *sFormula ); + + typedef Hash varHash; + varHash hVars; + + typedef struct Func + { + double operator()( double x ) + { + return 0.0; + } + } Func; + + typedef Hash funcHash; + funcHash hFunc; + + typedef struct FuncSin : Func + { + double operator()( double x ) + { + return sin( x ); + } + } FuncSin; + +private: + enum + { + symEOS, + symAdd, + symSubtract, + symMultiply, + symDivide, + symOpenParen, + symCloseParen, + symNumber, + symVariable, + symExponent, + symModulus + }; + + typedef uint8_t symType; + + std::stack sOper; + std::stack sValue; + +private: + symType getPrec( symType nOper ); + symType nextToken( char **sBuf ); + void reduce( bool bCloseParen = false ); +}; + +#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 @@ +#include "fstring.h" +#include "hash.h" + +template<> uint32_t __calcHashCode( const FString &k ) +{ + return __calcHashCode( k.c_str() ); +} + +template<> bool __cmpHashKeys( const FString &a, const FString &b ) +{ + return a == b; +} + 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 @@ +#ifndef F_STRING_H +#define F_STRING_H + +#include +#include +#include "serializable.h" +#include "serializer.h" + +template< typename chr > +struct FStringChunk +{ + long nLength; + chr *pData; + FStringChunk *pNext; +}; + +/** + * Flexible String class. This class was designed with string passing and + * generation in mind. Like the standard string class you can specify what + * datatype to use for each character. Unlike the standard string class, + * collection of appended and prepended terms is done lazily, making long + * operations that involve many appends very inexpensive. In addition internal + * ref-counting means that if you pass strings around between functions there's + * almost no overhead in time or memory since a reference is created and no + * data is actually copied. This also means that you never need to put any + * FBasicString into a ref-counting container class. + */ +template< typename chr, typename chralloc=std::allocator, typename chunkalloc=std::allocator > > +class FBasicString : public Serializable +{ +#ifndef VALTEST +#define cpy( dest, src, size ) memcpy( dest, src, size*sizeof(chr) ) +#endif +private: + typedef struct FStringChunk Chunk; + typedef struct FBasicString MyType; + +public: + FBasicString() : + nLength( 0 ), + pnRefs( NULL ), + pFirst( NULL ), + pLast( NULL ) + { + } + + FBasicString( const chr *pData ) : + nLength( 0 ), + pnRefs( NULL ), + pFirst( NULL ), + pLast( NULL ) + { + append( pData ); + } + + FBasicString( const chr *pData, long nLength ) : + nLength( 0 ), + pnRefs( NULL ), + pFirst( NULL ), + pLast( NULL ) + { + append( pData, nLength ); + } + + FBasicString( const MyType &rSrc ) : + nLength( 0 ), + pnRefs( NULL ), + pFirst( NULL ), + pLast( NULL ) + { + // Here we have no choice but to copy, since the other guy is a const. + // In the case that the source were flat, we could get a reference, it + // would make some things faster, but not matter in many other cases. + + joinShare( rSrc ); + //copyFrom( rSrc ); + } + + FBasicString( const MyType &rSrc, long nLength ) : + nLength( 0 ), + pnRefs( NULL ), + pFirst( NULL ), + pLast( NULL ) + { + append( rSrc.pFirst->pData, nLength ); + } + + FBasicString( const MyType &rSrc, long nStart, long nLength ) : + nLength( 0 ), + pnRefs( NULL ), + pFirst( NULL ), + pLast( NULL ) + { + append( rSrc.pFirst->pData+nStart, nLength ); + } + + FBasicString( long nSize ) : + nLength( nSize ), + pnRefs( NULL ), + pFirst( NULL ), + pLast( NULL ) + { + pFirst = pLast = newChunk( nSize ); + } + + virtual ~FBasicString() + { + clear(); + } + + void append( const chr *pData ) + { + long nLen; + for( nLen = 0; pData[nLen] != (chr)0; nLen++ ); + + Chunk *pNew = newChunk( nLen ); + cpy( pNew->pData, pData, nLen ); + + appendChunk( pNew ); + } + + void append( const chr *pData, long nLen ) + { + Chunk *pNew = newChunk( nLen ); + + cpy( pNew->pData, pData, nLen ); + + appendChunk( pNew ); + } + + void prepend( const chr *pData ) + { + long nLen; + for( nLen = 0; pData[nLen] != (chr)0; nLen++ ); + + Chunk *pNew = newChunk( nLen ); + cpy( pNew->pData, pData, nLen ); + + prependChunk( pNew ); + } + + void prepend( const chr *pData, long nLen ) + { + Chunk *pNew = newChunk( nLen ); + + cpy( pNew->pData, pData, nLen ); + + prependChunk( pNew ); + } + + void clear() + { + realClear(); + } + + void resize( long nNewSize ) + { + if( nLength == nNewSize ) + return; + + flatten(); + + Chunk *pNew = newChunk( nNewSize ); + long nNewLen = (nNewSizepData, pFirst->pData, nNewLen ); + pNew->pData[nNewLen] = (chr)0; + aChr.deallocate( pFirst->pData, pFirst->nLength+1 ); + aChunk.deallocate( pFirst, 1 ); + pFirst = pLast = pNew; + nLength = nNewSize; + } + + long getSize() const + { + return nLength; + } + + chr *getStr() + { + if( pFirst == NULL ) + return NULL; + + flatten(); + return pFirst->pData; + } + + const chr *getStr() const + { + if( pFirst == NULL ) + return NULL; + + flatten(); + return pFirst->pData; + } + + chr *c_str() + { + if( pFirst == NULL ) + return NULL; + + flatten(); + return pFirst->pData; + } + + const chr *c_str() const + { + if( pFirst == NULL ) + return NULL; + + flatten(); + return pFirst->pData; + } + + MyType &operator +=( const chr *pData ) + { + append( pData ); + + return (*this); + } + + MyType &operator +=( const MyType &rSrc ) + { + rSrc.flatten(); + append( rSrc.pFirst->pData, rSrc.nLength ); + + return (*this); + } + + MyType &operator +=( const chr pData ) + { + chr tmp[2] = { pData, (chr)0 }; + append( tmp ); + + return (*this); + } + + MyType &operator =( const chr *pData ) + { + clear(); + append( pData ); + + return (*this); + } + + MyType &operator =( const MyType &rSrc ) + { + //if( rSrc.isFlat() ) + //{ + joinShare( rSrc ); + //} + //else + //{ + // copyFrom( rSrc ); + //} + // + + return (*this); + } + + bool operator ==( const chr *pData ) const + { + if( pFirst == NULL ) { + if( pData == NULL ) + return true; + return false; + } + + flatten(); + const chr *a = pData; + chr *b = pFirst->pData; + for( ; *a!=(chr)0; a++, b++ ) + { + if( *a != *b ) + return false; + } + + return true; + } + + bool operator ==( const MyType &pData ) const + { + if( pFirst == pData.pFirst ) + return true; + if( pFirst == NULL ) + return false; + + flatten(); + pData.flatten(); + const chr *a = pData.pFirst->pData; + chr *b = pFirst->pData; + for( ; *a!=(chr)0; a++, b++ ) + { + if( *a != *b ) + return false; + } + + return true; + } + + bool operator !=(const chr *pData ) const + { + return !(*this == pData); + } + + bool operator !=(const MyType &pData ) const + { + return !(*this == pData); + } + + chr &operator[]( long nIndex ) + { + flatten(); + + return pFirst->pData[nIndex]; + } + + const chr &operator[]( long nIndex ) const + { + flatten(); + + return pFirst->pData[nIndex]; + } + + bool isWS( long nIndex ) const + { + flatten(); + + return pFirst->pData[nIndex]==' ' || pFirst->pData[nIndex]=='\t' + || pFirst->pData[nIndex]=='\r' || pFirst->pData[nIndex]=='\n'; + } + + bool isAlpha( long nIndex ) const + { + flatten(); + + return (pFirst->pData[nIndex] >= 'a' && pFirst->pData[nIndex] <= 'z') + || (pFirst->pData[nIndex] >= 'A' && pFirst->pData[nIndex] <= 'Z'); + } + + void toLower() + { + flatten(); + unShare(); + + for( long j = 0; j < nLength; j++ ) + { + if( pFirst->pData[j] >= 'A' && pFirst->pData[j] <= 'Z' ) + pFirst->pData[j] -= 'A'-'a'; + } + } + + void toUpper() + { + flatten(); + unShare(); + + for( long j = 0; j < nLength; j++ ) + { + if( pFirst->pData[j] >= 'a' && pFirst->pData[j] <= 'z' ) + pFirst->pData[j] += 'A'-'a'; + } + } + + void serialize( class Serializer &ar ) + { + if( ar.isLoading() ) + { + clear(); + long nLen; + ar >> nLen; + + Chunk *pNew = newChunk( nLen ); + ar.read( pNew->pData, nLen*sizeof(chr) ); + appendChunk( pNew ); + } + else + { + flatten(); + + ar << nLength; + ar.write( pFirst->pData, nLength*sizeof(chr) ); + } + } + +private: + void flatten() const + { + if( isFlat() ) + return; + + if( pFirst == NULL ) + return; + + unShare(); + + Chunk *pNew = newChunk( nLength ); + chr *pos = pNew->pData; + Chunk *i = pFirst; + for(;;) + { + cpy( pos, i->pData, i->nLength ); + pos += i->nLength; + i = i->pNext; + if( i == NULL ) + break; + } + realClear(); + + pLast = pFirst = pNew; + nLength = pNew->nLength; + } + + void realClear() const + { + if( pFirst == NULL ) + return; + + if( isShared() ) + { + decRefs(); + } + else + { + Chunk *i = pFirst; + for(;;) + { + Chunk *n = i->pNext; + aChr.deallocate( i->pData, i->nLength+1 ); + aChunk.deallocate( i, 1 ); + if( n == NULL ) + break; + i = n; + } + pFirst = pLast = NULL; + nLength = 0; + } + } + + void copyFrom( const FBasicString &rSrc ) + { + if( rSrc.pFirst == NULL ) + return; + + decRefs(); + + Chunk *pNew = newChunk( rSrc.nLength ); + chr *pos = pNew->pData; + Chunk *i = rSrc.pFirst; + for(;;) + { + cpy( pos, i->pData, i->nLength ); + pos += i->nLength; + i = i->pNext; + if( i == NULL ) + break; + } + clear(); + + appendChunk( pNew ); + } + + bool isFlat() const + { + return (pFirst == pLast); + } + + bool isShared() const + { + return (pnRefs != NULL); + } + + Chunk *newChunk() const + { + Chunk *pNew = aChunk.allocate( 1 ); + pNew->pNext = NULL; + return pNew; + } + + Chunk *newChunk( long nLen ) const + { + Chunk *pNew = aChunk.allocate( 1 ); + pNew->pNext = NULL; + pNew->nLength = nLen; + pNew->pData = aChr.allocate( nLen+1 ); + pNew->pData[nLen] = (chr)0; + return pNew; + } + + void appendChunk( Chunk *pNewChunk ) + { + unShare(); + + if( pFirst == NULL ) + pLast = pFirst = pNewChunk; + else + { + pLast->pNext = pNewChunk; + pLast = pNewChunk; + } + + nLength += pNewChunk->nLength; + } + + void prependChunk( Chunk *pNewChunk ) + { + unShare(); + + if( pFirst == NULL ) + pLast = pFirst = pNewChunk; + else + { + pNewChunk->pNext = pFirst; + pFirst = pNewChunk; + } + + nLength += pNewChunk->nLength; + } + + void joinShare( MyType &rSrc ) + { + clear(); + + if( !rSrc.isFlat() ) + rSrc.flatten(); + + rSrc.initCount(); + pnRefs = rSrc.pnRefs; + (*pnRefs)++; + nLength = rSrc.nLength; + pFirst = rSrc.pFirst; + pLast = rSrc.pLast; + } + + void joinShare( const MyType &rSrc ) + { + clear(); + + rSrc.flatten(); + + if( !rSrc.isShared() ) + { + rSrc.pnRefs = new uint32_t; + (*rSrc.pnRefs) = 1; + } + pnRefs = rSrc.pnRefs; + (*pnRefs)++; + nLength = rSrc.nLength; + pFirst = rSrc.pFirst; + pLast = rSrc.pLast; + } + + /** + * This takes an object that was shared and makes a copy of the base data + * that was being shared so that this copy can be changed. This should be + * added before any call that will change this object; + */ + void unShare() const + { + if( isShared() == false ) + return; + + Chunk *pNew = newChunk( nLength ); + chr *pos = pNew->pData; + Chunk *i = pFirst; + for(;;) + { + cpy( pos, i->pData, i->nLength ); + pos += i->nLength; + i = i->pNext; + if( i == NULL ) + break; + } + decRefs(); + pLast = pFirst = pNew; + nLength = pNew->nLength; + } + + /** + * This decrements our ref count and pulls us out of the share. If the ref + * count hits zero because of this, it destroys the share. This is not + * safe to call on it's own, it's much better to call unShare. + */ + void decRefs() const + { + if( isShared() ) + { + (*pnRefs)--; + if( (*pnRefs) == 0 ) + destroyShare(); + else + { + pnRefs = NULL; + pFirst = NULL; + pLast = NULL; + nLength = 0; + } + } + } + + /** + * While the unShare function removes an instance from a share, this + * function destroys the data that was in the share, removing the share + * itself. This should only be called when the refcount for the share has + * or is about to reach zero. + */ + void destroyShare() const + { + delete pnRefs; + pnRefs = NULL; + realClear(); + } + +#ifdef VALTEST + void cpy( chr *dest, const chr *src, long count ) const + { + for( int j = 0; j < count; j++ ) + { + *dest = *src; + dest++; + src++; + } + } +#endif + + void initCount() const + { + if( !isShared() ) + { + pnRefs = new uint32_t; + (*pnRefs) = 1; + } + } + +private: + mutable long nLength; + mutable uint32_t *pnRefs; + mutable Chunk *pFirst; + mutable Chunk *pLast; + + mutable chralloc aChr; + mutable chunkalloc aChunk; +}; + +typedef FBasicString FString; + +#include "hash.h" +template<> uint32_t __calcHashCode( const FString &k ); +template<> bool __cmpHashKeys( const FString &a, const FString &b ); + + +#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 @@ +#include "hash.h" + +subExceptionDef( HashException ) + +template<> uint32_t __calcHashCode( const int &k ) +{ + return k; +} + +template<> bool __cmpHashKeys( const int &a, const int &b ) +{ + return a == b; +} + +template<> uint32_t __calcHashCode( const unsigned int &k ) +{ + return k; +} + +template<> bool __cmpHashKeys( const unsigned int &a, const unsigned int &b ) +{ + return a == b; +} + +template<> +uint32_t __calcHashCode( const char * const &k ) +{ + if (k == NULL) + { + return 0; + } + + unsigned long int nPos = 0; + for( const char *s = k; *s; s++ ) + { + nPos = *s + (nPos << 6) + (nPos << 16) - nPos; + } + + return nPos; +} + +template<> bool __cmpHashKeys( const char * const &a, const char * const &b ) +{ + if( a == b ) + return true; + + for(int j=0; a[j] == b[j]; j++ ) + if( a[j] == '\0' ) + return true; + + return false; +} + +template<> +uint32_t __calcHashCode( char * const &k ) +{ + if (k == NULL) + { + return 0; + } + + unsigned long int nPos = 0; + for( const char *s = k; *s; s++ ) + { + nPos = *s + (nPos << 6) + (nPos << 16) - nPos; + } + + return nPos; +} + +template<> bool __cmpHashKeys( char * const &a, char * const &b ) +{ + if( a == b ) + return true; + + for(int j=0; a[j] == b[j]; j++ ) + if( a[j] == '\0' ) + return true; + + return false; +} + +template<> uint32_t __calcHashCode( const std::string &k ) +{ + std::string::size_type j, sz = k.size(); + const char *s = k.c_str(); + + unsigned long int nPos = 0; + for( j = 0; j < sz; j++, s++ ) + { + nPos = *s + (nPos << 6) + (nPos << 16) - nPos; + } + + return nPos; +} + +template<> bool __cmpHashKeys( const std::string &a, const std::string &b ) +{ + return a == b; +} + +template<> uint32_t __calcHashCode( const Hashable &k ) +{ + return 0; + //return k.getHashCode(); +} + +template<> bool __cmpHashKeys( const Hashable &a, const Hashable &b ) +{ + return false; + //return a.compareForHash( b ); +} + 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 @@ +#ifndef HASH_H +#define HASH_H + +#include +#include +#include +#include +#include +#include "exceptionbase.h" +#include "hashable.h" +#include "serializable.h" +#include "serializer.h" + +#define bitsToBytes( n ) (n/32+(n%32>0 ? 1 : 0)) + +subExceptionDecl( HashException ) + +enum eHashException +{ + excodeNotFilled +}; + +template +uint32_t __calcHashCode( const T &k ); + +template +bool __cmpHashKeys( const T &a, const T &b ); + +struct __calcNextTSize_fast +{ + uint32_t operator()( uint32_t nCapacity, uint32_t nFill, uint32_t nDeleted ) const + { + if( nDeleted >= nCapacity/2 ) + return nCapacity; + return nCapacity*2+1; + } +}; + +template, typename valuealloc = std::allocator, typename challoc = std::allocator > +class Hash; + +template< typename key, typename _value, typename sizecalc = __calcNextTSize_fast, typename keyalloc = std::allocator, typename valuealloc = std::allocator<_value>, typename challoc = std::allocator > +struct HashProxy +{ + friend class Hash; +private: + HashProxy( Hash &h, key *k, uint32_t nPos, uint32_t hash ) : + hsh( h ), + pKey( k ), + nPos( nPos ), + hash( hash ), + bFilled( false ) + { + } + + HashProxy( Hash &h, uint32_t nPos, _value *pValue ) : + hsh( h ), + nPos( nPos ), + pValue( pValue ), + bFilled( true ) + { + } + + Hash &hsh; + key *pKey; + uint32_t nPos; + _value *pValue; + uint32_t hash; + bool bFilled; + +public: + operator _value &() + { + if( bFilled == false ) + throw HashException( + excodeNotFilled, + "No data assosiated with that key." + ); + return *pValue; + } + + _value &value() + { + if( bFilled == false ) + throw HashException( + excodeNotFilled, + "No data assosiated with that key." + ); + return *pValue; + } + + bool isFilled() + { + return bFilled; + } + + void erase() + { + if( bFilled ) + { + hsh._erase( nPos ); + hsh.onDelete(); + } + } + + _value operator=( _value nval ) + { + if( bFilled ) + { + hsh.va.destroy( pValue ); + hsh.va.construct( pValue, nval ); + hsh.onUpdate(); + } + else + { + hsh.fill( nPos, *pKey, nval, hash ); + hsh.onInsert(); + } + + return nval; + } + + _value *operator->() + { + if( bFilled == false ) + throw HashException( + excodeNotFilled, + "No data assosiated with that key." + ); + return pValue; + } +}; + +template +class Hash +{ + friend struct HashProxy; +public: + Hash() : + nCapacity( 11 ), + nFilled( 0 ), + nDeleted( 0 ), + bFilled( NULL ), + bDeleted( NULL ), + aKeys( NULL ), + aValues( NULL ), + aHashCodes( NULL ) + { + nKeysSize = bitsToBytes( nCapacity ); + bFilled = ca.allocate( nKeysSize ); + bDeleted = ca.allocate( nKeysSize ); + clearBits(); + + aHashCodes = ca.allocate( nCapacity ); + aKeys = ka.allocate( nCapacity ); + aValues = va.allocate( nCapacity ); + } + + Hash( const Hash &src ) : + nCapacity( src.nCapacity ), + nFilled( 0 ), + nDeleted( 0 ), + bFilled( NULL ), + bDeleted( NULL ), + aKeys( NULL ), + aValues( NULL ), + aHashCodes( NULL ) + { + nKeysSize = bitsToBytes( nCapacity ); + bFilled = ca.allocate( nKeysSize ); + bDeleted = ca.allocate( nKeysSize ); + clearBits(); + + aHashCodes = ca.allocate( nCapacity ); + aKeys = ka.allocate( nCapacity ); + aValues = va.allocate( nCapacity ); + + for( uint32_t j = 0; j < src.nCapacity; j++ ) + { + if( src.isFilled( j ) ) + { + insert( src.aKeys[j], src.aValues[j] ); + } + } + } + + Hash &operator=( const Hash &src ) + { + for( uint32_t j = 0; j < nCapacity; j++ ) + { + if( isFilled( j ) ) + if( !isDeleted( j ) ) + { + va.destroy( &aValues[j] ); + ka.destroy( &aKeys[j] ); + } + } + va.deallocate( aValues, nCapacity ); + ka.deallocate( aKeys, nCapacity ); + ca.deallocate( bFilled, nKeysSize ); + ca.deallocate( bDeleted, nKeysSize ); + ca.deallocate( aHashCodes, nCapacity ); + + nFilled = 0; + nDeleted = 0; + nCapacity = src.nCapacity; + nKeysSize = bitsToBytes( nCapacity ); + bFilled = ca.allocate( nKeysSize ); + bDeleted = ca.allocate( nKeysSize ); + clearBits(); + + aHashCodes = ca.allocate( nCapacity ); + aKeys = ka.allocate( nCapacity ); + aValues = va.allocate( nCapacity ); + + for( uint32_t j = 0; j < src.nCapacity; j++ ) + { + if( src.isFilled( j ) ) + { + insert( src.aKeys[j], src.aValues[j] ); + } + } + + return *this; + } + + virtual ~Hash() + { + for( uint32_t j = 0; j < nCapacity; j++ ) + { + if( isFilled( j ) ) + if( !isDeleted( j ) ) + { + va.destroy( &aValues[j] ); + ka.destroy( &aKeys[j] ); + } + } + va.deallocate( aValues, nCapacity ); + ka.deallocate( aKeys, nCapacity ); + ca.deallocate( bFilled, nKeysSize ); + ca.deallocate( bDeleted, nKeysSize ); + ca.deallocate( aHashCodes, nCapacity ); + } + + uint32_t getCapacity() + { + return nCapacity; + } + + uint32_t getFill() + { + return nFilled; + } + + uint32_t size() + { + return nFilled-nDeleted; + } + + uint32_t getDeleted() + { + return nDeleted; + } + + virtual HashProxy operator[]( key k ) + { + uint32_t hash = __calcHashCode( k ); + bool bFill; + uint32_t nPos = probe( hash, k, bFill ); + + if( bFill ) + { + return HashProxy( *this, nPos, &aValues[nPos] ); + } + else + { + return HashProxy( *this, &k, nPos, hash ); + } + } + + virtual void insert( key k, value v ) + { + uint32_t hash = __calcHashCode( k ); + bool bFill; + uint32_t nPos = probe( hash, k, bFill ); + + if( bFill ) + { + va.destroy( &aValues[nPos] ); + va.construct( &aValues[nPos], v ); + onUpdate(); + } + else + { + fill( nPos, k, v, hash ); + onInsert(); + } + } + + virtual void erase( key k ) + { + uint32_t hash = __calcHashCode( k ); + bool bFill; + uint32_t nPos = probe( hash, k, bFill ); + + if( bFill ) + { + _erase( nPos ); + onDelete(); + } + } + + struct iterator; + virtual void erase( struct iterator &i ) + { + if( this != &i.hsh ) + throw HashException("This iterator didn't come from this Hash."); + if( isFilled( i.nPos ) && !isDeleted( i.nPos ) ) + { + _erase( i.nPos ); + onDelete(); + } + } + + virtual void clear() + { + for( uint32_t j = 0; j < nCapacity; j++ ) + { + if( isFilled( j ) ) + if( !isDeleted( j ) ) + { + va.destroy( &aValues[j] ); + ka.destroy( &aKeys[j] ); + onDelete(); + } + } + + clearBits(); + } + + virtual value &get( key k ) + { + uint32_t hash = __calcHashCode( k ); + bool bFill; + uint32_t nPos = probe( hash, k, bFill ); + + if( bFill ) + { + return aValues[nPos]; + } + else + { + throw HashException( + excodeNotFilled, + "No data assosiated with that key." + ); + } + } + + virtual bool has( key k ) + { + bool bFill; + probe( __calcHashCode( k ), k, bFill, false ); + + return bFill; + } + + typedef struct iterator + { + friend class Hash; + private: + iterator( Hash &hsh ) : + hsh( hsh ), + nPos( 0 ), + bFinished( false ) + { + nPos = hsh.getFirstPos( bFinished ); + } + + iterator( Hash &hsh, bool bDone ) : + hsh( hsh ), + nPos( 0 ), + bFinished( bDone ) + { + } + + Hash &hsh; + uint32_t nPos; + bool bFinished; + + public: + iterator operator++( int ) + { + if( bFinished == false ) + nPos = hsh.getNextPos( nPos, bFinished ); + + return *this; + } + + iterator operator++() + { + if( bFinished == false ) + nPos = hsh.getNextPos( nPos, bFinished ); + + return *this; + } + + bool operator==( const iterator &oth ) + { + if( bFinished != oth.bFinished ) + return false; + if( bFinished == true ) + { + return true; + } + else + { + if( oth.nPos == nPos ) + return true; + return false; + } + } + + bool operator!=( const iterator &oth ) + { + return !(*this == oth ); + } + + iterator operator=( const iterator &oth ) + { + if( &hsh != &oth.hsh ) + throw HashException( + "Cannot mix iterators from different hash objects."); + nPos = oth.nPos; + bFinished = oth.bFinished; + } + + std::pair operator *() + { + return hsh.getAtPos( nPos ); + } + + key &getKey() + { + return hsh.getKeyAtPos( nPos ); + } + + value &getValue() + { + return hsh.getValueAtPos( nPos ); + } + }; + + iterator begin() + { + return iterator( *this ); + } + + iterator end() + { + return iterator( *this, true ); + } + + std::list getKeys() + { + std::list lKeys; + + for( uint32_t j = 0; j < nCapacity; j++ ) + { + if( isFilled( j ) ) + { + if( !isDeleted( j ) ) + { + lKeys.push_back( aKeys[j] ); + } + } + } + + return lKeys; + } + +protected: + virtual void onInsert() {} + virtual void onUpdate() {} + virtual void onDelete() {} + virtual void onReHash() {} + + virtual void clearBits() + { + for( uint32_t j = 0; j < nKeysSize; j++ ) + { + bFilled[j] = bDeleted[j] = 0; + } + } + + virtual void fill( uint32_t loc, key &k, value &v, uint32_t hash ) + { + bFilled[loc/32] |= (1<<(loc%32)); + va.construct( &aValues[loc], v ); + ka.construct( &aKeys[loc], k ); + aHashCodes[loc] = hash; + nFilled++; + //printf("Filled: %d, Deleted: %d, Capacity: %d\n", + // nFilled, nDeleted, nCapacity ); + } + + virtual void _erase( uint32_t loc ) + { + bDeleted[loc/32] |= (1<<(loc%32)); + va.destroy( &aValues[loc] ); + ka.destroy( &aKeys[loc] ); + nDeleted++; + //printf("Filled: %d, Deleted: %d, Capacity: %d\n", + // nFilled, nDeleted, nCapacity ); + } + + virtual std::pair getAtPos( uint32_t nPos ) + { + return std::pair(aKeys[nPos],aValues[nPos]); + } + + virtual key &getKeyAtPos( uint32_t nPos ) + { + return aKeys[nPos]; + } + + virtual value &getValueAtPos( uint32_t nPos ) + { + return aValues[nPos]; + } + + virtual uint32_t getFirstPos( bool &bFinished ) + { + for( uint32_t j = 0; j < nCapacity; j++ ) + { + if( isFilled( j ) ) + if( !isDeleted( j ) ) + return j; + } + + bFinished = true; + return 0; + } + + virtual uint32_t getNextPos( uint32_t nPos, bool &bFinished ) + { + for( uint32_t j = nPos+1; j < nCapacity; j++ ) + { + if( isFilled( j ) ) + if( !isDeleted( j ) ) + return j; + } + + bFinished = true; + return 0; + } + + uint32_t probe( uint32_t hash, key k, bool &bFill, bool rehash=true ) + { + uint32_t nCur = hash%nCapacity; + + // First we scan to see if the key is already there, abort if we + // run out of probing room, or we find a non-filled entry + for( int8_t j = 0; + isFilled( nCur ) && j < 32; + nCur = (nCur + (1< uint32_t __calcHashCode( const int &k ); +template<> bool __cmpHashKeys( const int &a, const int &b ); + +template<> uint32_t __calcHashCode( const unsigned int &k ); +template<> bool __cmpHashKeys( const unsigned int &a, const unsigned int &b ); + +template<> uint32_t __calcHashCode( const char * const &k ); +template<> bool __cmpHashKeys( const char * const &a, const char * const &b ); + +template<> uint32_t __calcHashCode( char * const &k ); +template<> bool __cmpHashKeys( char * const &a, char * const &b ); + +template<> uint32_t __calcHashCode( const std::string &k ); +template<> bool __cmpHashKeys( const std::string &a, const std::string &b ); + +template<> uint32_t __calcHashCode( const Hashable &k ); +template<> bool __cmpHashKeys( const Hashable &a, const Hashable &b ); + +template +Serializer &operator<<( Serializer &ar, Hash &h ) +{ + ar << h.size(); + for( typename Hash::iterator i = h.begin(); i != h.end(); i++ ) + { + std::pair p = *i; + ar << p.first << p.second; + } + + return ar; +} + +template +Serializer &operator>>( Serializer &ar, Hash &h ) +{ + h.clear(); + uint32_t nSize; + ar >> nSize; + + for( uint32_t j = 0; j < nSize; j++ ) + { + key k; value v; + ar >> k >> v; + h.insert( k, v ); + } + + return ar; +} + +template +Serializer &operator&&( Serializer &ar, Hash &h ) +{ + if( ar.isLoading() ) + { + return ar >> h; + } + else + { + return ar << h; + } +} + +#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 @@ +#ifndef HASHABLE_H +#define HASHABLE_H + +class Hashable +{ +public: + virtual ~Hashable() {}; + virtual unsigned long int getHashCode() = 0; + virtual bool compareForHash( Hashable &other ) = 0; +}; + +#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 @@ +#include "hashfunction.h" + +HashFunction::HashFunction() +{ +} + +HashFunction::~HashFunction() +{ +} + 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 @@ +#ifndef HASH_FUNCTION +#define HASH_FUNCTION + +/** This represents the shell of a hash function. It must be aggregated in + * order to be used. Please read about it's two functions for specificatins + * relating to what values will be passed to them and what they should return + * for creating your own hash functions. + *@author Mike Buland. + */ +class HashFunction +{ +public: + /** + * Standard Constructor. + */ + HashFunction(); + + /** + * Standard Deconstructor. + */ + virtual ~HashFunction(); + + /** Hashes the value represnted by id. This must return a fairly unique + * number in the range of 0-2^32 (or whatever the size of an unsigned long + * is on your system) based on the id given. The faster the number changes + * the better in a general sence. The return value will be the index + * (after probing takes place) to the data assosiated with an id, so this + * function should always produce the same number for any given id. + *@param id The identifier to use to create a unique numerical identifier. + *@returns A mostly unique numerical identifier generated using the given + * id. + */ + virtual unsigned long int hash( const void *id ) = 0; + + /** This function must compare two ids in the format that this hashfunction + * accepts. For example, if the hash function hashes strings it should + * probably { return strcmp( id1, id2 ) == 0 }. + *@param id1 One value to use in the comparison + *@param id2 Another value to use in the comparison + *@returns True if the two values match, otherwise false. + */ + virtual bool cmpIDs( const void *id1, const void *id2 ) = 0; + +// virtual void *createPersistantID( const void *id ) = 0; +// virtual void destroyPersistantID( const void *id ) = 0; +}; + +#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 @@ +#include +#include +#include +#include "hashfunctioncasestring.h" + +HashFunctionCaseString::HashFunctionCaseString() +{ +} + +HashFunctionCaseString::~HashFunctionCaseString() +{ +} + +unsigned long int HashFunctionCaseString::hash( const void *id ) +{ + const char *str = (const char *)id; + unsigned long int nPos = 0; + for( int j = 0; str[j] != '\0'; j++ ) + { + nPos = tolower(str[j]) + (nPos << 6) + (nPos << 16) - nPos; +// nPos += nPos<<16|(((unsigned long int)tolower(str[j]))<<((j*7)%24)); + } + return nPos; +} + +bool HashFunctionCaseString::cmpIDs( const void *id1, const void *id2 ) +{ + const char *str1 = (const char *)id1; + const char *str2 = (const char *)id2; + + int j; + for( j = 0; str1[j] != '\0' && str2[j] != '\0'; j++ ) + { + if( tolower(str1[j]) != tolower(str2[j]) ) + return false; + } + return (str1[j]==str2[j]); +} + 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 @@ +#ifndef HASH_FUNCTION_CASE_STRING +#define HASH_FUNCTION_CASE_STRING + +#include "hashfunction.h" + +/** A hash function for string data. This hash function does strings, but is + * actually generalized to handle any binary stream of characters terminated + * by a null character. This is different than HashFunctionString in that + * this does comparisons without regaurd to case. + *@author Mike Buland. + */ +class HashFunctionCaseString : public HashFunction +{ +public: + /** + * Standard Constructor. + */ + HashFunctionCaseString(); + + /** + * Standard Deconstructor. + */ + virtual ~HashFunctionCaseString(); + unsigned long int hash( const void *id ); + bool cmpIDs( const void *id1, const void *id2 ); +}; + +#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 @@ +#include "hashfunctionint.h" + +HashFunctionInt::HashFunctionInt() +{ +} + +HashFunctionInt::~HashFunctionInt() +{ +} + +unsigned long int HashFunctionInt::hash( const void *id ) +{ + return (unsigned long)(id); +} + +bool HashFunctionInt::cmpIDs( const void *id1, const void *id2 ) +{ + return (unsigned long)(id1) == (unsigned long)(id2); +} + 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 @@ +#ifndef HASH_FUNCTION_INT +#define HASH_FUNCTION_INT + +#include "hashfunction.h" + +/** A hash function for integer data. Really, this does almost nothing except + * ensure we're dealing with positive indicies. + *@author Mike Buland. + */ +class HashFunctionInt : public HashFunction +{ +public: + /** + * Standard Constructor. + */ + HashFunctionInt(); + + /** + * Standard Deconstructor. + */ + virtual ~HashFunctionInt(); + unsigned long int hash( const void *id ); + bool cmpIDs( const void *id1, const void *id2 ); +}; + +#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 @@ +#include "hashfunctionstring.h" +#ifndef NULL +#define NULL ((void *) 0) +#endif + +HashFunctionString::HashFunctionString() +{ +} + +HashFunctionString::~HashFunctionString() +{ +} + +unsigned long int HashFunctionString::hash( const void *id ) +{ + if (id == NULL) + { + return 0; + } + + unsigned long int nPos = 0; + for( const char *s = (const char *)id; *s; s++ ) + { + nPos = *s + (nPos << 6) + (nPos << 16) - nPos; + } + return nPos; +} + +bool HashFunctionString::cmpIDs( const void *id1, const void *id2 ) +{ + if (id1 == NULL || id2 == NULL) + { + return false; + } + if (id1 == id2) + { + return true; + } + + const char *str1 = (const char *)id1; + const char *str2 = (const char *)id2; + + int j; + for( j = 0; str1[j] != '\0' && str2[j] != '\0'; j++ ) + { + if( str1[j] != str2[j] ) + return false; + } + return (str1[j]==str2[j]); +} + 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 @@ +#ifndef HASH_FUNCTION_STRING +#define HASH_FUNCTION_STRING + +#include "hashfunction.h" + +/** A hash function for string data. This hash function does strings, but is + * actually generalized to handle any binary stream of characters terminated + * by a null character. + *@author Mike Buland. + */ +class HashFunctionString : public HashFunction +{ +public: + /** + * Standard Constructor. + */ + HashFunctionString(); + + /** + * Standard Deconstructor. + */ + virtual ~HashFunctionString(); + unsigned long int hash( const void *id ); + bool cmpIDs( const void *id1, const void *id2 ); +}; + +#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 @@ +#include +#include +#include + +#include "hashtable.h" + +HashTable::HashTable( HashFunction *hNewFunc, unsigned long int nInitSize, bool bAllowDupes ) +{ + hFunc = hNewFunc; + nTableSize = nextPrime( nInitSize ); + aTable = new HashNode[nTableSize]; + //for( int j = 0; j < nTableSize; j++ ) if( aTable[j].id || aTable[j].data || aTable[j].bDeleted ) printf("Unclean entry\n"); + nSize = 0; + nFilled = 0; + this->bAllowDupes = bAllowDupes; +} + +HashTable::~HashTable() +{ + delete[] aTable; + delete hFunc; +} + +void HashTable::set( int j, const void *newID, const void *newData ) +{ + if( newData == NULL ) + { + printf("Inserting NULL data is indestinguishable from uninserted data!\n"); + } + aTable[j].id = newID; + aTable[j].data = newData; +} + +void HashTable::clear() +{ + memset( aTable, 0, sizeof(HashNode) * nTableSize ); +} + +bool HashTable::isFilled( int j ) +{ + return (aTable[j].id != NULL)||(aTable[j].bDeleted); +} + +void HashTable::reHash( unsigned long int nNewSize ) +{ + HashNode *aOldTable = aTable; + unsigned long int oldSize = nTableSize; + + // If the table can still be used if we just get rid of deleted items, don't + // change the size of the table, otherwise, go ahead and use the number + // passed in. + if( nSize > nTableSize>>1 ) + { + nTableSize = nextPrime( nNewSize ); + } + + aTable = newTable( nTableSize ); + //for( int j = 0; j < nTableSize; j++ ) if( aTable[j].id || aTable[j].data || aTable[j].bDeleted ) printf("Unclean entry\n"); + + nSize = 0; + nFilled = 0; + + for( unsigned long int j = 0; j < oldSize; j++ ) + { + if( aOldTable[j].id != NULL && aOldTable[j].bDeleted == false ) + { + insert( aOldTable[j].id, aOldTable[j].data ); + } + } + + delete[] aOldTable; +} + +unsigned long int HashTable::probe( unsigned long int nStart, const void *id ) +{ + int nHash = nStart; + nStart = nStart%nTableSize; + if( bAllowDupes == true ) + { + for( + unsigned long int j=0; + isFilled( nStart ) && j < 32; + nStart = (nStart+(1<cmpIDs( aTable[nStart].id, id ) == true && + aTable[nStart].bDeleted == false ) + { + return nStart; + } + } + } + } + // This is our insurance, if the table is full, then go ahead and rehash, + // then try again. + if( isFilled( nStart ) ) + { + reHash( getCapacity()*2 ); + return probe( nHash, id ); + } + return nStart; +} + +HashTable::HashNode *HashTable::newTable( unsigned long int nNewSize ) +{ + return new HashNode[nNewSize]; +} + +#ifdef HASH_DEBUG_VIS +void HashTable::printDebugLine( const char *exData ) +{ + char *buf = new char[getCapacity()+3]; + int j; + buf[0] = '['; + for( j = 0; j < getCapacity(); j++ ) + { + buf[j+1] = (aTable[j].bDeleted)?('X'):((isFilled( j ))?('#'):('-')); + } + buf[j+1] = ']'; + buf[j+2] = '\0'; + printf("%s %s\n", buf, exData ); + delete[] buf; +} +#endif + +bool HashTable::insert( const void *id, const void *data ) +{ + unsigned long int nPos = probe( hFunc->hash( id ), id )%nTableSize; + + if( bAllowDupes == true ) + { + if( aTable[nPos].id == NULL && aTable[nPos].bDeleted == false ) + { + set( nPos, id, data ); +#ifdef HASH_DEBUG_VIS + printDebugLine( (const char *)id ); +#endif + nSize++; + nFilled++; + return true; + } + else + { + return false; + } + } + else + { + if( aTable[nPos].id == NULL && aTable[nPos].bDeleted == false ) + { + set( nPos, id, data ); +#ifdef HASH_DEBUG_VIS + printDebugLine( (const char *)id ); +#endif + nSize++; + nFilled++; + return true; + } + else if( hFunc->cmpIDs( aTable[nPos].id, id ) == true ) + { + set( nPos, id, data ); +#ifdef HASH_DEBUG_VIS + printDebugLine( (const char *)id ); +#endif + return true; + } + else + { + return false; + } + } +} + +const void *HashTable::get( const void *id, unsigned long int nSkip ) +{ + unsigned long int nPos = hFunc->hash( id )%nTableSize; + + for( unsigned long int j=0; j < 32; nPos = (nPos+(1<cmpIDs( id, aTable[nPos].id ) ) + { + if( nSkip == 0 ) + { + return aTable[nPos].data; + } + else + { + nSkip--; + } + } + } + } + + if( bAllowDupes ) + { + unsigned long int nOldPos = nPos; + for( nPos++; nPos != nOldPos; nPos=(nPos+1)%nTableSize ) + { + if( !isFilled( nPos ) ) return NULL; + if( aTable[nPos].bDeleted == false ) + { + if( hFunc->cmpIDs( id, aTable[nPos].id ) ) + { + if( nSkip == 0 ) + { + return aTable[nPos].data; + } + else + { + nSkip--; + } + } + } + } + } + + return NULL; +} + +const void *HashTable::getKey( const void *id, unsigned long int nSkip ) +{ + unsigned long int nPos = hFunc->hash( id )%nTableSize; + + for( unsigned long int j=0; j < 32; nPos = (nPos+(1<cmpIDs( id, aTable[nPos].id ) ) + { + if( nSkip == 0 ) + { + return aTable[nPos].id; + } + else + { + nSkip--; + } + } + } + } + + if( bAllowDupes ) + { + unsigned long int nOldPos = nPos; + for( nPos++; nPos != nOldPos; nPos=(nPos+1)%nTableSize ) + { + if( !isFilled( nPos ) ) return NULL; + if( aTable[nPos].bDeleted == false ) + { + if( hFunc->cmpIDs( id, aTable[nPos].id ) ) + { + if( nSkip == 0 ) + { + return aTable[nPos].id; + } + else + { + nSkip--; + } + } + } + } + } + + return NULL; +} + +void *HashTable::getFirstItemPos() +{ + HashPos *pos = new HashPos; + return pos; +} + +const void *HashTable::getItemData( void *xPos ) +{ + return aTable[((HashPos *)xPos)->nPos].data; +} + +const void *HashTable::getItemID( void *xPos ) +{ + return aTable[((HashPos *)xPos)->nPos].id; +} + +void *HashTable::getNextItemPos( void *xPos ) +{ + HashPos *pos = (HashPos *)xPos; + if( pos->bStarted == false ) + { + pos->bStarted = true; + pos->nPos = 0; + } + else + { + pos->nPos++; + } + if( pos->nPos < nTableSize ) + { + for( ; pos->nPos < nTableSize; pos->nPos++ ) + { + if( isFilled( pos->nPos ) && + aTable[pos->nPos].bDeleted == false ) + { + return xPos; + } + } + } + + delete pos; + + return NULL; +} + +// Big-O sqrt(n) +// Change this to be erethpothynies table with a storage +// lookup later on. +bool HashTable::isPrime (int num) +{ + if (num == 2) // the only even prime + return true; + else if (num % 2 == 0) // other even numbers are composite + return false; + else + { + //bool prime = true; + int divisor = 3; + int upperLimit = static_cast(sqrt(num) + 1); + while (divisor <= upperLimit) + { + if (num % divisor == 0) + return false; + // prime = false; + divisor +=2; + } + return true; + } +} + +// Big-O n^(3/2) +int HashTable::nextPrime( int base ) +{ + int nPrime; + for( nPrime = base; isPrime( nPrime ) == false; nPrime++ ); + return nPrime; +} + +unsigned long int HashTable::getCapacity() +{ + return nTableSize; +} + +unsigned long int HashTable::getSize() +{ + return nSize; +} + +double HashTable::getLoad() +{ + return (double)(nFilled)/(double)(nTableSize); +} + +const void *HashTable::operator[](const void *id) +{ + return get( id ); +} + +bool HashTable::del( const void *id, int nSkip ) +{ + unsigned long int nPos = hFunc->hash( id )%nTableSize; + + for( unsigned long int j=0; j < 32; nPos = (nPos+(1<cmpIDs( id, aTable[nPos].id ) && + aTable[nPos].bDeleted == false ) + { + if( nSkip == 0 ) + { + aTable[nPos].bDeleted = true; + nSize--; +#ifdef HASH_DEBUG_VIS + printDebugLine( (const char *)id ); +#endif + return true; + } + else + { + nSkip--; + } + } + } + + return false; +} + 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 @@ +/**\hashtable.h + * Describes the HashFunction, HashFunctionString, and HashTable classes. It + * was just easier to put them all in one set of files. + *@author Mike Buland + */ + +#ifndef HASH_TABLE_H +#define HASH_TABLE_H + +//Uncomment this line to see a cool text-mode visualization of what's going on +//#define HASH_DEBUG_VIS 1 + +#include +#include +#include + +#include "hashfunction.h" + +/** + * A simple yet flexable hash-table. This uses several tricks to help ensure + * that the table is always running at maximum efficiency. You no longer have + * to specify a "danger fill level" when more space is needed a rehash is + * automatically trigered. Deleting elements is fully supported, as well as + * duplicate elements. To work with and allow duplicates simple construct your + * HashTable the way you normally would, but when deleting or getting elements + * you can specify a skip value. This effectively allows you to treat elements + * with duplicate ID's as though they were in a zero-based array. The first + * element inserted with a given ID would be at skip zero, the next at skip 1 + * and so on. This allows you to quickly search for elements with duplicate + * names, just stop when you get a null for a skip number, i.e. + *
+ *   for( int j = 0;; j++ )
+ *   {
+ *       void *pData = hash.get( myID, j );
+ *       if( !pData ) break;
+ *       // Do something interesting with pData
+ *   }
+ * 
+ * There are new features in this HashTable that also allow for memory saving + * when dealing with systems where many elements are being deleted from the + * table. In those cases the elements deleted cannot be simply deleted, instead + * they have to be marked as deleted and hidden from the user, but maintained in + * the table so that future hashing operations don't fail. When rehashing + * occurs all elements marked as deleted are quietly removed. In these cases, + * if the number of deleted items would free enough space in the table for the + * table to be used efficiently without resizing, it is left the same size and + * rehashing is performed effectively in place, allowing the deleted items to + * be removed. + *
+ * For info on adding new hashing algorithms, please see the HashFunction class. + *@author Mike Buland + *@todo Fix probing for tables that allow duplicates, and delete an item, then + * insert an item with the same name. + */ +class HashTable +{ +public: + /** Constructs a hash table. + *@param hNewFunc A pointer to a hashfunction class to use. If this is + * null the default general string type will be used. + *@param nInitSize The initial size of the hashtable. + *@param bAllowDupes Setting this value to true allows the system to + * insert more than one copy of any given key. This can be tricky, and + * will require you to use the nSkip parameter on the get function. + */ + HashTable( HashFunction *hNewFunc, unsigned long int nInitSize, bool bAllowDupes=false ); + + /** + * Destroys the hashtable, cleaning up all internal storage, but not stored + * elements. Also deletes the HashFunction passed in in the constructor. + */ + virtual ~HashTable(); + + /** Inserts an item into the hashtable. This function will trigger a + * rehash if adding another item would force the table's load factor over + * the danger level. + *@param id used to find the data later. + *@param data The data item to insert into the table with the identifier + * id + *@returns True if insertion was successfull, and false if it failed. + */ + bool insert( const void *id, const void *data ); + + /** Gets an item in the hashtable based on the id of that item. If there + * is more than one item with the same id you can use the nSkip parameter + * to access all of them. + *@param id The id of the item you're trying to find. + *@param nSkip The number of items with that id to skip before returning + * with the requested item. + *@returns A pointer to the data stored at the given id. + */ + const void *get( const void *id, unsigned long int nSkip=0 ); + + const void *getKey( const void *id, unsigned long int nSkip=0 ); + + /** Gets the total capacity of the hashtable. This is actually the number + * of total positions available inside the hashtable at the moment. This + * will change when the hashtable's load exceeds the danger level. + * Please note that this is NOT the actual amount of space available. + * In reality you can only access about 45-50 percent of that space. + *@returns The total capacity. + */ + unsigned long int getCapacity(); + + /** Gets the number of filled in items in the hash table. This is roughly + * equivelent to the getSize function assosiated with the Lists. + *@returns The number of filled in items in the hash table. + */ + unsigned long int getSize(); + + /** Gets the load (percentage) of filled in items in the table. This is + * technically the size divided by the capacity, but is definately usefull + * since it's required to check if it's time to rehash. + *@returns The table load in the range 0.0 to 1.0 + */ + double getLoad(); + + /** Sets up an xPos object for use indexing the items in the table. Call + * this first and follow the directions for getNextItemPos below to + * iterate through every item in the table, while avoiding the empty + * spaces. + *@returns A pointer to a xPos object telling the hashtable where to find + * the item you're looking at. + */ + void *getFirstItemPos(); + + /** Get the item's data that is being pointed to by xPos. This is only + * valid after xPos was created using getFirstItemPos and getNextItemPos + * was called at least once. + *@param xPos supplied by getFirstItemPos. + *@returns The key value that was used to insert the data into the table. + */ + const void *getItemData( void *xPos ); + + /** Get the item's ID that is being pointed to by xPos. This is only + * valid after xPos was created using getFirstItemPos and getNextItemPos + * was called at least once. + *@param xPos supplied by getFirstItemPos. + *@returns The key value that was used to insert the data into the table. + */ + const void *getItemID( void *xPos ); + + /** Used for iterating through a hash table sequentially. This will + * update the xPos pointer to point to the next time, all ready to + * be accessed with getItemID and getItemData. This must be called at + * least once before xPos is meaningful, and will return a NULL when it + * has reached the last item. + *@param xPos This must be an object created by a call to the function + * getFirstItemPos, and is only meaningful to the internal routines. + * Aborting a call in the middle (not running to the end of the table) + * may result in a memory leak at the moment. + *@returns xPos if still iterating through the list, otherwise it will + * return NULL when the end has been reached and the xPos variable has + * been deleted. + */ + void *getNextItemPos( void *xPos ); + + /** A helpful operator to make accessing items easier. Please note that + * this simply returns a pointer to the data stored internally, and cannot + * be used like the STL operator to store new data, use insert for that. + *@param id The identifier used to store the requested item. + *@returns The data value assosiated with the given id, or NULL if it + * wasn't found in the table. + */ + const void *operator[](const void *id); + + /** + * Delete the specified item from the hashtable. This actually keeps the + * data and marks it deleted. For all intents and purposes to the user it + * is deleted, except that the space is still used until a rehash is forced. + * This means that in hashtables where elements are being inserted and + * deleted frequently you may run into a higher rate of expansion. + *@param id The ID to delete. + *@param nSkip The number of similar id's to skip before deleting in a + * hashtable that allows duplicates. + *@returns True if the element was found and deleted, false otherwise. + */ + bool del( const void *id, int nSkip=0 ); + + /** + * Deletes every entry in the hash table. See the notes on del to see what + * this means, except that since no data is being kept, the entire table is + * just marked as usable space. + */ + void clear(); + +private: + /** + * Contains info related to a position in the hashtable. Used for + * searching through hashtables one item at a time, in order. This class + * should never be created by anything but a HashTable, and should never + * be referenced directly. Instead the hashtable returns a void pointer, + * which is what should be passed back in next time you use a search + * function. Always finish a search, since the object is deleted at the + * end of the search. + *@author Mike Buland + */ + class HashPos + { + public: + /** Create a blank HashPos. */ + HashPos() { bStarted=false; nPos = 0; }; + /** Has the search been started? */ + bool bStarted; + /** The position (index) into the backend storage structure. */ + unsigned long int nPos; + }; + + /** + * All data related to a single element in the hashtable. This should + * really only be used and manipulated by the HashTable itself. + *@author Mike Buland + */ + typedef struct HashNode + { + public: + /** Create a new, empty HashNode. */ + HashNode() { id = NULL; data = NULL; bDeleted = false; }; + /** A pointer to the original ID that was used to key the data. */ + const void *id; + /** A pointer to the data stored along with the above ID. */ + const void *data; + /** Weather or not this data should really...exist */ + bool bDeleted; + } HashNode; + +private: + /** + * Just sets the values in the element to some friendly values. + *@param newID The new ID to store. + *@param newData The new Data to store. + */ + void set( int j, const void *newID, const void *newData ); + /** + * Tells you if the node is filled or not. + *@returns True=an ID has been stored here, False=no ID. + */ + bool isFilled( int j ); + /** + * This actually resizes, but since every resize requires a reHash to go + * along with it, that's the name. This actually creates a new buffer for + * all of the contained data and then pulls every old element that was in + * the old table out and performs the hashing placement calculations again. + * This function skips all data that was marked as deleted, so at this + * point it really will be. + *@param nNewSize The new size to set the table to while re-hashing. + *@returns True if the operation was successful, false otherwise. + */ + void reHash( unsigned long int nNewSize ); + + /** + * Helper function to allocate a new table. Really just does the memory + * allocation. + *@param nNewSize The size of the table to generate. + *@returns A new, blank array of HashNode objects the size you specified. + */ + HashNode *newTable( unsigned long int nNewSize ); + + /** + * This function is used once an actual hash code is obtained. nStart is + * the given hash code, which is then wrapped to the size of the table. If + * there is data at that location, tests are performed to see if it's the + * right one. If it is, then it is returned, otherwise a series of further + * tests based on a 2^n search pattern is performed. The position of the + * requested data in the back-end storage is returned if found, otherwise + * another less useful value is returned... + *@param nStart The initial hashcode of the ID testing for. + *@param id A pointer to the id that is being searched for. + *@returns The real location of the data requested. + */ + unsigned long int probe( unsigned long int nStart, const void *id ); + + /** + * Simple helper function to determine if a number is prime or not. + * This function runs in sqrt(n) time. + *@param num Number to test for prime-hood. + *@returns True if the number is prime, false otherwise. + */ + bool isPrime( int num ); + + /** + * Given any number, this function finds the first number after it that is + * prime. Since this number is a multiple internally it's rare that the + * starting number would be prime. + *@param base The number to start the prime search on. + *@returns The first prime after the number given. + */ + int nextPrime( int base ); + +#ifdef HASH_DEBUG_VIS + void printDebugLine( const char *exData ); +#endif + + /** A pointer to the HashFunction subclass instance to use. */ + HashFunction *hFunc; + /** The complete array of HashNode objects to store data in. */ + HashNode *aTable; + /** The actual size of the table, not how many elements are in it. */ + unsigned long int nTableSize; + /** The number of elements that are in the table. */ + unsigned long int nSize; + /** The number of elements that are unavailable now. */ + unsigned long int nFilled; + /** Allow duplicate ID's in the table. */ + bool bAllowDupes; +}; + +#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 @@ +#include +#include +#include "http.h" +#include "hashfunctionstring.h" + +Http::Http( Connection *pConnection ) : hReqHeader( new HashFunctionString(), 100 ) +{ + pCon = pConnection; + nParseState = parseInit; +} + +Http::~Http() +{ + for( int j = 0; j < lStrings.getSize(); j++ ) + { + delete (std::string *)lStrings[j]; + } +} + +bool Http::parseRequest() +{ + for(;;) + { + pCon->readInput(); + switch( nParseState ) + { + case parseInit: + { + int nLen = pCon->scanInputFor( CR ); + if( nLen == -1 ) + { + return false; + } + else + { + nReqType = getRequestType( pCon->getInput() ); + pCon->usedInput( pCon->scanInputFor(' ')+1 ); + + nLen = pCon->scanInputFor(' '); + sReqURI.append( pCon->getInput(), nLen ); + pCon->usedInput( nLen+1 ); + + if( !strncmp( pCon->getInput(), "HTTP/", 5 ) ) + { + char mbuf[2]={'\0','\0'}; + unsigned char major, minor; + + pCon->usedInput( 5 ); + mbuf[0] = pCon->getInput()[0]; + major = (unsigned char)atoi(mbuf); + mbuf[0] = pCon->getInput()[2]; + minor = (unsigned char)atoi(mbuf); + setRequestVersion( major, minor ); + if( checkRequestVer() ) + { + nParseState = parseHeader; + } + else + { + setResponseStatus( statusHTTPVersionNotSupported ); + //printf("Verson not supported.\n"); + return true; + } + + pCon->usedInput( 5 ); + } + else + { + setResponseStatus( statusBadRequest ); + } + + //return false; + } + } + break; + + case parseHeader: + { + int nLen = pCon->scanInputFor( CR ); + //printf("nLen = %d: :::%s:::\n", nLen, pCon->getInput() ); + if( nLen == -1 ) + { + pCon->readInput( 1, 0); + } + else if( nLen == 0 ) + { + // We've got our double-newline, time for content. + pCon->usedInput( 2 ); + setResponseStatus( statusOK ); + return true; + } + else + { + nLen = pCon->scanInputFor(':'); + if( nLen == -1 ) + { + //printf("No colon? what are you trying to pull?\n"); + } + else + { + std::string *pName = new std::string( pCon->getInput(), nLen ); + lStrings.append( pName ); + pCon->usedInput( nLen+1 ); + + nLen = pCon->scanInputFor( CR ); + std::string *pValue = convSpaceString( pCon->getInput(), nLen ); + lStrings.append( pValue ); + pCon->usedInput( nLen+2 ); + + hReqHeader.insert( + pName->c_str(), + pValue->c_str() + ); + + //printf("::%s = \"%s\"\n", + // pName->c_str(), + // pValue->c_str() + // ); + } + } + } + break; + + case parseFinished: + break; + } + } +} + +bool Http::buildResponse( short nResponseCode, const char *sResponse ) +{ + if( nResponseCode > 0 ) + { + nResStatus = nResponseCode; + } + + if( sResponse == NULL ) + { + sResStatusStr = "uh yeah"; + } + else + { + sResStatusStr = sResponse; + } + + time_t curTime; + time( &curTime ); + gmtime_r( &curTime, &tResTime ); + + sServerStr = "libbu++ Http/0.0.1"; + bResPersistant = false; + + //char buf[30]; + //strftime( buf, 30, "%a, %d %b %Y %H:%M:%S GMT", &tResponseTime ); + + return true; +} + +bool Http::sendResponse() +{ + char buf[256]; + + sprintf( buf, "HTTP/1.1 %d %s\r\n", nResStatus, sResStatusStr.c_str() ); + pCon->appendOutput( buf ); + + strftime( buf, 256, "Date: %a, %d %b %Y %H:%M:%S GMT\r\n", &tResTime ); + pCon->appendOutput( buf ); + + sprintf( buf, "Server: %s\r\n", sServerStr.c_str() ); + pCon->appendOutput( buf ); + + if( bResPersistant ) + { + } + else + { + pCon->appendOutput("Connection: close\r\n"); + } + + sprintf( buf, "Content-Type: %s\r\n", sResMime.c_str() ); + pCon->appendOutput( buf ); + + sprintf( buf, "Content-Length: %d\r\n", sResContent.size() ); + pCon->appendOutput( buf ); + + pCon->appendOutput("\r\n"); + + pCon->appendOutput( sResContent.c_str(), sResContent.size() ); + + return true; +} + +void Http::setResponsePersistant( bool bPersistant ) +{ + bResPersistant = bPersistant; +} + +void Http::setResponseContent( const char *sMime, const char *sContent, int nLen ) +{ + sResMime = sMime; + sResContent.erase(); + sResContent.append( sContent, nLen ); +} + +std::string *Http::convSpaceString( const char *sStr, int nLen ) +{ + int nNewLen = 0; + bool bStart = true; + bool bSpace = false; + + for( int j = 0; j < nLen; j++ ) + { + if( sStr[j] == ' ' || sStr[j] == '\t' ) + { + if( bStart ) + { + } + else if( bSpace == false ) + { + bSpace = true; + nNewLen++; + } + } + else + { + bStart = false; + bSpace = false; + nNewLen++; + } + } + if( bSpace ) + { + nNewLen--; + } + + std::string *pSStr = new std::string; + //char *pStr = pSStr->c_str(); + nNewLen = 0; + bStart = true; + bSpace = false; + + for( int j = 0; j < nLen; j++ ) + { + if( sStr[j] == ' ' || sStr[j] == '\t' ) + { + if( bStart ) + { + } + else if( bSpace == false ) + { + bSpace = true; + *pSStr += ' '; + //pStr[nNewLen++] = ' '; + } + } + else + { + bStart = false; + bSpace = false; + *pSStr += sStr[j]; + //pStr[nNewLen++] = sStr[j]; + } + } + if( bSpace == true ) + { + nNewLen--; +// pStr[nNewLen] = '\0'; + } + + return pSStr; +} + +const char *Http::getRequestURI() +{ + return sReqURI.c_str(); +} + +short Http::getRequestType( const char *sType ) +{ + if( !strncmp( sType, "OPTIONS", 7 ) ) + { + return reqOptions; + } + else if( !strncmp( sType, "GET", 3 ) ) + { + return reqGet; + } + else if( !strncmp( sType, "HEAD", 4 ) ) + { + return reqHead; + } + else if( !strncmp( sType, "POST", 4 ) ) + { + return reqPost; + } + else if( !strncmp( sType, "PUT", 3 ) ) + { + return reqPut; + } + else if( !strncmp( sType, "DELETE", 6 ) ) + { + return reqDelete; + } + else if( !strncmp( sType, "TRACE", 5 ) ) + { + return reqTrace; + } + else if( !strncmp( sType, "CONNECT", 7 ) ) + { + return reqConnect; + } + else + { + printf(" Uh oh, extension!\n"); + return reqExtension; + } +} + +const char *Http::getRequestType( short nType ) +{ + switch( nType ) + { + case reqOptions: return "OPTIONS"; + case reqGet: return "GET"; + case reqHead: return "HEAD"; + case reqPost: return "POST"; + case reqPut: return "PUT"; + case reqDelete: return "DELETE"; + case reqTrace: return "TRACE"; + case reqConnect: return "CONNECT"; + case reqExtension: return "EXTENSION"; + default: return "INVALID VALUE"; + } +} + +short Http::getRequestType() +{ + return nReqType; +} + +const char *Http::getRequestTypeStr() +{ + return getRequestType( nReqType ); +} + +void Http::setResponseStatus( short nStatus ) +{ + nResStatus = nStatus; +} + +void Http::setRequestVersion( unsigned char nMajor, unsigned char nMinor ) +{ + cReqVersion = (nMajor<<4)|nMinor; +} + +unsigned char Http::getRequestMinorVer() +{ + return cReqVersion&0x0F; +} + +unsigned char Http::getRequestMajorVer() +{ + return cReqVersion>>4; +} + +bool Http::checkRequestVer() +{ + if( cReqVersion == HTTP11 ) + return true; + return false; +} + +const char *Http::getHeader( const char *lpStr ) +{ + return (const char *)hReqHeader[lpStr]; +} + 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 @@ +/**\file http.h + * Describe a Hyper Text Transfer Protocol processor. This class will allow + * any program to act as either an HTTP server, client, or both. It contains + * a number of additional helpers and subclasses. + *@author Mike Buland + */ + +#ifndef HTTP_H +#define HTTP_H + +#include +#include "connection.h" +#include "linkedlist.h" +#include "hashtable.h" + +#define CR '\r' /**< The ASCII value of a Carrage Return */ +#define LF '\n' /**< The ASCII value of a Line Feed */ +#define CRLF CR LF /**< Combo of CR+LF for use in http */ + +/** + * Macro to create combined http version codes. This just makes processing a + * little bit faster for the most part. + *@param maj Major version number, between 0 and 15 + *@param min Minor version number, between 0 and 15 + *@returns A one byte combined version number suitable for use in switches. + */ +#define HTTPVER( maj, min ) ((maj<<4)|(min)) + +#define HTTP10 HTTPVER( 1, 0 ) /**< Combined version code for http 1.0 */ +#define HTTP11 HTTPVER( 1, 1 ) /**< Combined version code for http 1.1 */ + +/** + * This is the master HTTP processing class. One instance handles one + * transaction, in the future a different mechanism may be thought up, but for + * now this means that you must create multiple objects to handle a single + * connection that contains multiple requests. + * In the constructor the Http class is given a connection object. This object + * should already be initialized and connected to whatever socket it wants to + * be sending and receiving data to and from. Once that's done you can call + * parseRequest if you're acting as a server, or a variety of buildRequest + * functions to create and send a request if you're a client. + * Please note that this class does not provide any HTTP or extended format + * processing systems, but will allow for mime types tables to be registered. + *@author Mike Buland + */ +class Http +{ +public: + /** + * Create an Http object tied to an existing connection object. + *@param pConnection The live connection object to deal with. + */ + Http( Connection *pConnection ); + + /** + * Standard Deconstructor. + */ + virtual ~Http(); + + /** + * Perform all parsing needed to figure out what an HTTP client wants from + * us. This will setup a number of properties in the Http object itself + * and has the possibility of setting one or more response states initially. + * These states should be checked for immediately after parsing to see if + * an appropriate error message should be generated. These errors can + * include issues with protocol, data formats, or unknown versions of the + * protocol. + *@returns True means that all processing is finished, false means that + * the parseRequest function should be called again when more data is + * ready. A return value of true does not indicate success, only that + * processing is finished, the getResponseStatus function should be called + * to see what status was set in the parse routine. A 200 indicates that + * as far as the parser is concerned, everything when smoothly. Otherwise + * it's your responsibility to build the appropriate error response body + * (like an html file) and send it as the response. + */ + bool parseRequest(); + + /** + * Get a request type's internal Http object id based on the string + * representation. These can be any HTTP/1.1 standard request type. + *@param sType The string that should be checked for type. This is in all + * caps, just like if it came from the HTTP client, which is most often + * the case. + *@returns The numerical ID of the given request type. Please note that + * HTTP/1.1 standard specifies that any string is valid here as long as + * the non-basic string is a request type understood by the serving + * software. This means that anything that is non-standard will return + * a type reqExtension and not an error. This is not a mistake. + */ + short getRequestType( const char *sType ); + + /** + * Get the string representation of an Http object request type integer ID. + * This is used mainly for debugging to be sure the system has what we + * think it has. + *@param nType The integer ID of the request type to process. + *@returns The HTTP/1.1 string representation of that Http object ID code. + */ + const char *getRequestType( short nType ); + + /** + * Returns the Http object request type ID code that is stored in the + * object by either the parseRequest function or use of the buildRequest + * functions. + *@returns The ID of the request type stored in the object. + */ + short getRequestType(); + + /** + * Same as getRequestType, only returns the string representation. + *@returns The string representation of the request type ID stored in the + * object. + */ + const char *getRequestTypeStr(); + + /** + * Sets the version of the request used by the system. This will be used + * by parse request, but is also part of the buildRequest tool functions. + *@param nMajor The major version number. + *@param nMinor The minor version number. + */ + void setRequestVersion( unsigned char nMajor, unsigned char nMinor ); + + /** + * Gets the major version number of the protocol used/to be used in this + * request. + *@returns The major version number of the request protocol. + */ + unsigned char getRequestMinorVer(); + + /** + * Gets the minor version number of the protocol used/to be used in this + * request. + *@returns The minor version number of the request protocol. + */ + unsigned char getRequestMajorVer(); + + /** + * Checks the stored request version against an internal table of supported + * protocol versions. + *@returns True if the protocol version is supported, false otherwise. + */ + bool checkRequestVer(); + + /** + * Converts an arbitrary string to a new string object with space saving + * operations performed ala the HTTP/1.1 specs. All leading and trailing + * whitespace is stripped, and all whitespace within the string is reduced + * to a single space char. + *@param sStr A pointer to the string data to process. + *@param nLen The length of the string to process. Since this function is + * often called on stream data, there is no null terminator where we need + * one. This is here for convinience so the data doesn't need to be hacked + * up or moved to an intermediate buffer. + *@returns A new string that may well be shorter than the original but that + * will have the same value as far as the HTTP/1.1 specs are concerned. + */ + std::string *convSpaceString( const char *sStr, int nLen ); + + /** + * Gets a string pointer to the URI that was/is being requested. This can + * be any RFC standard URI, with or without protocol and domain. + *@returns A pointer to the URI that was/is being requested. + */ + const char *getRequestURI(); + + /** + * Set a new response status. This status can be anything that the HTTP + * specs allow. Other values are allowed as well, but beware, not all + * servers/clients will accept values that are not in the tables in this + * class. + *@param nStatus The status to set. + */ + void setResponseStatus( short nStatus ); + + bool buildResponse( short nResponseCode=-1, const char *sResponse=NULL ); + void setResponseContent( const char *sMime, const char *sContent, int nLen ); + void setResponsePersistant( bool bPersistant ); + bool sendResponse(); + + enum + { + reqOptions, + reqGet, + reqHead, + reqPost, + reqPut, + reqDelete, + reqTrace, + reqConnect, + reqExtension + }; + + enum + { + statusContinue = 100, + statusSwitchProto = 101, + + statusOK = 200, + statusCreated = 201, + statusAccepted = 202, + statusNonAuthInfo = 203, + statusNoContent = 204, + statusResetContent = 205, + statusPartialContent = 206, + + statusMultiChoices = 300, + statusMovedPermanently = 301, + statusFound = 302, + statusSeeOther = 303, + statusNotModified = 304, + statusUseProxy = 305, + statusUnused = 306, + statusTempRedirect = 307, + + statusBadRequest = 400, + statusUnauthorized = 401, + statusPaymentRequired = 402, + statusForbidden = 403, + statusNotFound = 404, + statusMethodNotAllowed = 405, + statusNotAcceptable = 406, + statusProxyAuthRequired = 407, + statusRequestTimeout = 408, + statusConflict = 409, + statusGone = 410, + statusLengthRequired = 411, + statusPreconditionFailed = 412, + statusRequestEntityTooLarge = 413, + statusRequestURITooLong = 414, + statusUnsupportedMediaType = 415, + statusRequestedRangeNotSatisfiable = 416, + statusExpectationFailed = 417, + + statusInternalServerError = 500, + statusNotImplemented = 501, + statusBadGateway = 502, + statusServiceUnavailable = 503, + statusGatewayTimeout = 504, + statusHTTPVersionNotSupported = 505 + }; + + const char *getHeader( const char *lpStr ); + +private: + Connection *pCon; + unsigned char nParseState; + + short nReqType; + std::string *pReqStr; + std::string sReqURI; + unsigned char cReqVersion; + HashTable hReqHeader; + LinkedList lStrings; + + std::string sServerStr; + std::string sResMime; + std::string sResContent; + std::string sResStatusStr; + bool bResPersistant; + struct tm tResTime; + short nResStatus; + + enum + { + parseInit, + parseHeader, + parseFinished + }; +}; + +#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 @@ +#include "httpget.h" +#include "exceptions.h" +#include "connection.h" +#include + +char HttpGet::hexcode[]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; + +HttpGet::HttpGet() : + nPort( 80 ), + sUserAgent("libbu++; HttpGet") +{ +} + +HttpGet::HttpGet( const std::string &url ) : + nPort( 80 ) +{ + setURL( url ); +} + +HttpGet::~HttpGet() +{ +} + +void HttpGet::setURL( const std::string &url ) +{ + int len = url.size(); + //printf("Full URL: %s\n", url.c_str() ); + int pos = url.find("://"); + sProto.assign( url, 0, pos ); + //printf("Protocol: %s\n", sProto.c_str() ); + + int pos2 = url.find("/", pos+3 ); + if( pos2 >= 0 ) + { + sHost.assign( url, pos+3, pos2-pos-3 ); + } + else + { + sHost.assign( url, pos+3, std::string::npos ); + } + + int pos3 = sHost.find(":"); + if( pos3 >= 0 ) + { + nPort = strtol( sHost.c_str()+pos3+1, NULL, 10 ); + sHost.erase( pos3 ); + } + //printf("Hostname: %s\n", sHost.c_str() ); + //printf("Port: %d\n", nPort ); + + pos3 = url.find("?", pos2+1 ); + if( pos3 >= 0 ) + { + sPath.assign( url, pos2, pos3-pos2 ); + //printf("Path: %s\n", sPath.c_str() ); + for(;;) + { + int end = pos3+1; + for(; url[end] != '=' && url[end] != '&' && end < len; end++ ); + std::string sKey, sValue; + sKey.assign( url, pos3+1, end-pos3-1 ); + if( url[end] == '=' ) + { + pos3 = end; + for( end++; url[end] != '&' && end < len; end++ ); + sValue.assign( url, pos3+1, end-pos3-1 ); + pos3 = end; + } + else + { + } + lParams.push_back( StringPair( sKey, sValue ) ); + //printf("Param: %s = %s\n", sKey.c_str(), sValue.c_str() ); + if( end+1 >= len ) break; + } + } + else + { + sPath.assign( url, pos2, std::string::npos ); + //printf("Path: %s\n", sPath.c_str() ); + } + + //printf("\n"); +} + +void HttpGet::addParam( const std::string &key, const std::string &value ) +{ + lParams.push_back( StringPair( key, value ) ); +} + +std::string HttpGet::escape( const std::string &src ) +{ + std::string escaped(""); + for( std::string::const_iterator i = src.begin(); i != src.end(); i++ ) + { + unsigned char j = *i; + if( (j >= '0' && j <= '9') || + (j >= 'a' && j <= 'z') || + (j >= 'A' && j <= 'Z') || + j == '$' || + j == '-' || + j == '_' || + j == '.' || + j == '+' || + j == '!' || + j == '*' || + j == '\'' || + j == '(' || + j == ')' ) + { + escaped += j; + } + else + { + escaped += "%"; + escaped += hexcode[j>>4]; + escaped += hexcode[j&0x0F]; + } + } + + return escaped; +} + +SBuffer *HttpGet::get() +{ + std::string sData; + sData = "GET " + sPath; + if( !lParams.empty() ) + { + sData += "?"; + for( std::list::iterator i = lParams.begin(); + i != lParams.end(); i++ ) + { + if( i != lParams.begin() ) + sData += "&"; + + if( (*i).second == "" ) + { + sData += escape( (*i).first ); + } + else + { + sData += escape( (*i).first ); + sData += "="; + sData += escape( (*i).second ); + } + } + } + + sData += " HTTP/1.1\r\n" + "User-Agent: " + sUserAgent + "\r\n" + "Connection: close\r\n" + "Host: " + sHost + "\r\n" + "Content-type: application/x-www-form-urlencoded\r\n\r\n"; + + //printf("Connection content:\n\n%s\n\n", sData.c_str() ); + + Connection con; + //printf("Opening connection...\n"); + con.open( sHost.c_str(), nPort ); + { + int nSocket = con.getSocket(); + fd_set rfds, wfds, efds; + int retval; + + FD_ZERO(&rfds); + FD_SET(nSocket, &rfds); + FD_ZERO(&wfds); + FD_SET(nSocket, &wfds); + FD_ZERO(&efds); + FD_SET(nSocket, &efds); + + struct timeval tv; + tv.tv_sec = 4; + tv.tv_usec = 0; + + //printf("Selecting on socket, can we read, write, etc?\n"); + retval = select( nSocket+1, &rfds, &wfds, &efds, &tv ); + /*printf("About to write: sock=%d, r=%d, w=%d, e=%d, ret=%d\n", + nSocket, + FD_ISSET( nSocket, &rfds ), + FD_ISSET( nSocket, &wfds ), + FD_ISSET( nSocket, &efds ), + retval + );*/ + + if( retval == 0 ) + { + //printf("Timeout on connection.\n"); + con.close(); + throw ExceptionBase("Connection Timeout on open.\n"); + } + + } + con.appendOutput( sData.c_str(), sData.size() ); + //printf("Writing to socket...\n"); + con.writeOutput(); + //printf("Data written...\n"); + int nSec = 5; + int nUSec = 0; + int nLastAmnt = con.getInputAmnt(); + try + { + double dTotTime = 0.0; + //printf("About to read input...\n"); + while( con.readInput( nSec, nUSec, &nSec, &nUSec ) ) + { + if( nLastAmnt == con.getInputAmnt() ) + { + if( nSec <= 0 && nUSec <= 0 ) + { + //printf("out of time, closing up.\n"); + con.close(); + throw ExceptionBase("Connection Timeout.\n"); + } + if( nSec == 5 && nUSec == 0 ) + { + //printf("No new data, breaking.\n"); + break; + } + } + else + { + dTotTime += (5.0-(nSec+nUSec/1000000.0)); + printf("\rRead %db at %.2fkb/sec", + con.getInputAmnt(), + ((double)(con.getInputAmnt())/1024.0) / dTotTime + ); + fflush( stdout ); + nSec = 5; + nUSec = 0; + nLastAmnt = con.getInputAmnt(); + } + } + } + catch( ConnectionException &e ) + { + //con.close(); + if( strcmp( e.what(), "Connection closed" ) ) + printf("\nConnectionException: %s\n", e.what() ); + } + + int total = con.getInputAmnt(); + const char *dat = con.getInput(); + //printf("\n===> Final size %d\n", total ); + for( int i = 0; i < total; i++ ) + { + if( !memcmp( dat+i, "\r\n\r\n", 4 ) ) + { + SBuffer *buf = new SBuffer; + buf->write( dat+i+4, total-i-4 ); + buf->setPos( 0 ); + con.close(); + return buf; + } + } + con.close(); + + //printf("\n\n%s\n\n", dat ); + + throw ExceptionBase("Something went wrong, incomplete response? fix this.\n"); +} + 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 @@ +#ifndef HTTP_GET_H +#define HTTP_GET_H + +#include +#include +#include +#include + +#include "sbuffer.h" + +class HttpGet +{ +public: + HttpGet(); + HttpGet( const std::string &url ); + virtual ~HttpGet(); + + void setURL( const std::string &url ); + void addParam( const std::string &key, const std::string &value ); + void setUserAgent( const std::string &sUserAgent ) + { + this->sUserAgent = sUserAgent; + } + void setHost( const std::string &sHost ) + { + this->sHost = sHost; + } + + std::string escape( const std::string &src ); + SBuffer *get(); + +private: + std::string sProto; + std::string sHost; + std::string sPath; + int nPort; + std::string sUserAgent; + typedef std::pair StringPair; + std::list lParams; + static char hexcode[]; + +}; + +#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 @@ +#include "linkedlist.h" + +LinkedList::LinkedList( ) +{ + pBase = NULL; + pTop = NULL; + pLast = NULL; + nSize = 0; + nLast = -1; +} + +LinkedList::~LinkedList( ) +{ +/* + Link *pCur = pBase; + while( pCur ) + { + Link *pLast = pCur; + pCur = pCur->pNext; + delete pLast; + } +*/ + empty(); +} + +void *LinkedList::getAt( int index ) +{ + if( index < 0 || index >= nSize ) + return NULL; + + return getPtrTo( index )->pData; +} + +void LinkedList::append( void *data ) +{ + if( pBase == NULL ) + { + pBase = new Link( data ); + pTop = pBase; + nSize++; + } + else + { + pTop->pNext = new Link( data ); + pTop = pTop->pNext; + nSize++; + } +} + +void LinkedList::insertBefore( void *data, int pos ) +{ + if( pos < 0 || pos > nSize ) + return; + + if( pos == 0 ) + { + Link *pTmp = new Link( data, pBase ); + if( pBase == NULL ) + { + pTop = pTmp; + } + pBase = pTmp; + if( nLast >= 0 ) nLast++; + nSize++; + } + else + { + Link *pCur; + if( (pCur = getPtrTo( pos-1 )) == NULL ) + { + return; + } + Link *pNew = new Link( data, pCur->pNext ); + pCur->pNext = pNew; + if( pNew->pNext == NULL ) + { + pTop = pNew; + } + if( nLast >= pos ) nLast++; + nSize++; + } +} + +int LinkedList::getSize( ) +{ + return nSize; +} + +bool LinkedList::isEmpty( ) +{ + if( nSize == 0 ) + return true; + return false; +} + +void LinkedList::deleteAt( int index ) +{ + if( index >= nSize || + pBase == NULL ) + return; + + if( index == 0 ) + { + Link *pTmp = pBase->pNext; + delete pBase; + pBase = pTmp; + if( nLast >= 0 ) nLast--; + nSize--; + if( pBase == NULL ) + { + pTop = NULL; + } + else if( pBase->pNext == NULL ) + { + pTop = pBase; + } + } + else + { + Link *pCur = getPtrTo( index-1 ); + if( pCur->pNext == pTop ) + { + pTop = pCur; + } + Link *pTmp; + if( pCur->pNext == NULL ) + { + pTmp = NULL; + } + else + { + pTmp = pCur->pNext->pNext; + } + delete pCur->pNext; + pCur->pNext = pTmp; + if( nLast == index ) nLast = -1; + else if( index < nLast ) nLast--; + nSize--; + } +} + +void LinkedList::empty() +{ + while( nSize > 0 ) + { + deleteAt( 0 ); + } +} + +void LinkedList::setSize( int newSize ) +{ + if( newSize < nSize ) + { + // Delete items off of the end of the list. + while( nSize > newSize ) + { + deleteAt( nSize-1 ); + } + } + else + { + // Add null items to the end of the list. + while( nSize < newSize ) + { + append( NULL ); + } + } +} + +void LinkedList::setAt( int index, void *data ) +{ + if( index >= nSize || index < 0 ) + return; + + getPtrTo( index )->pData = data; +} + +LinkedList::Link *LinkedList::getPtrTo( int index ) +{ + if( index < 0 || index >= nSize ) + return NULL; + if( index == nLast ) + { + return pLast; + } + if( index == 0 ) + { + pLast = pBase; + nLast = 0; + return pBase; + } + else + { + Link *pCur = pBase; + int nCur = 0; + if( nLast < index && nLast >= 0 ) + { + pCur = pLast; + nCur = nLast; + } + while( nCur != index ) + { + pCur = pCur->pNext; + nCur++; + } + nLast = index; + pLast = pCur; + return pCur; + } +} 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 @@ +/**@file + * Describes the LinkedList implementation of the List ADT. + *@author Mike Buland + */ + +#ifndef LINKEDLIST_H +#define LINKEDLIST_H + +#include +#include "list.h" + +/** A linked-item implementation of the List ADT. Since the data is linked + * sequentially this is a great choice for lists that will grow and shrink + * a lot, but don't require as much random access. This implementation + * includes optomizations that make iterating through data, and appending + * items to the list take O(1) time. + *@author Mike Buland + */ +class LinkedList : public List +{ +public: + /** + * Construct a blank LinkedList. + */ + LinkedList(); + + /** + * Delete all list data, but do not delete any of the contained elements. + */ + virtual ~LinkedList(); + + void *getAt( int nIndex ); + void append( void *pData ); + void insertBefore( void *pData, int nPos = 0 ); + int getSize( ); + bool isEmpty( ); + void deleteAt( int nIndex ); + void empty(); + void setSize( int nNewSize ); + void setAt( int nIndex, void *pData ); + +private: + /** + * A link in the linked list. + */ + class Link + { + public: + /** + * Construct an empty link. + */ + Link() + { + pData = NULL; + pNext = NULL; + } + /** + * Construct a link filled in with useful data. + *@param newData The data this link should hold. + *@param newNext The next link that this link should point to. + */ + Link( void *newData = NULL, Link * newNext = NULL ) + { + pData = newData; + pNext = newNext; + } + void *pData; /**< A pointer to the contained data. */ + Link *pNext; /**< A pointer to the next link in the chain */ + }; + + /** + * Finds a pointer to the link at index index. This is the core function + * called for all seek operations, and has been optimized as heavily as + * possible. + *@param index The zero-based index of the desired element. + *@returns A pointer to the requested Link, or NULL if it isn't found. + */ + Link *getPtrTo( int index ); + Link *pBase; /**< The first link in the list. */ + Link *pTop; /**< The Last link in the list. */ + Link *pLast; /**< The previously requested link. */ + int nSize; /**< The number of contained links. */ + int nLast; /**< The index of the previously requested link. */ +}; + +#endif + 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 @@ +#include "linkmessage.h" +#include + +LinkMessage::LinkMessage( int nNewMsg ) +{ + nMsg = nNewMsg; +} + +LinkMessage::~LinkMessage() +{ +} + +/* +void LinkMessage::setBroadcast( bool bOn ) +{ + bBroadcast = bOn; +} + +bool LinkMessage::isBroadcast() +{ + return bBroadcast; +} + + +void LinkMessage::setFromID( int id ) +{ + nFromLinkID = id; +} + +int LinkMessage::getFromID() +{ + return nFromLinkID; +} + +void LinkMessage::setToID( int id ) +{ + nTargetLinkID = id; +} + +int LinkMessage::getToID() +{ + return nTargetLinkID; +} +*/ 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 @@ +/**\file linkmessage.h + */ + +#ifndef LINKMESSAGE_H +#define LINKMESSAGE_H + +/** + * A message to be broadcast accross ProgramLinks in a ProgramChain. Generally + * one would make a subclass of this in order to transmit more useful + * information, but sometimes it isn't necesarry. + *@author Mike Buland + */ +class LinkMessage +{ +public: + /** + * Construct a blank LinkMessage. + */ + LinkMessage() {}; + + /** + * Deconstruct a LinkMessage. + */ + virtual ~LinkMessage(); + + /** + * Create a LinkMessage object with a specific message assosiated with it + * to start with. + *@param nNewMsg The message to use in the Message object. + */ + LinkMessage( int nNewMsg ); + + /** + * The message contained in the Message object. + */ + int nMsg; +}; + +#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 @@ +#include "linkmessenger.h" + +LinkMessenger::LinkMessenger() : + pFirst( NULL ), + pLast( NULL ) +{ +} + +LinkMessenger::~LinkMessenger() +{ +} + +void LinkMessenger::enqueueMessage( LinkMessage *pMsg ) +{ + if( pLast == NULL ) + { + pFirst = pLast = new Link; + pLast->pMsg = pMsg; + pLast->pNext = NULL; + } + else + { + pLast->pNext = new Link; + pLast = pLast->pNext; + pLast->pMsg = pMsg; + pLast->pNext = NULL; + } +} + +LinkMessage *LinkMessenger::dequeueMessage() +{ + if( pFirst == NULL ) + return NULL; + + Link *pTmp = pFirst; + pFirst = pFirst->pNext; + LinkMessage *pRet = pTmp->pMsg; + delete pTmp; + return pRet; +} + 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 @@ +#ifndef LINK_MESSENGER_H +#define LINK_MESSENGER_H + +#include +#include +#include "linkmessage.h" + +class LinkMessenger +{ +public: + LinkMessenger(); + virtual ~LinkMessenger(); + + void enqueueMessage( LinkMessage *pMsg ); + LinkMessage *dequeueMessage(); + bool hasMessages() + { + return (pFirst != NULL); + } + +private: + typedef struct Link + { + LinkMessage *pMsg; + Link *pNext; + }; + Link *pFirst; + Link *pLast; + +}; + +#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 @@ +#include "list.h" + +List::List( ) +{ +} + +List::~List( ) +{ +} + 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 @@ +#ifndef LIST_H +#define LIST_H + + +/** The basic List class ADT. This, on it's own, does absolutely nothing, but + * does define all standard interface functions to access a list. + *@author Mike Buland + */ +class List +{ +public: + /** + * Construct a list. + */ + List(); + + /** + * Desconstruct a list. + */ + virtual ~List(); + + /** Gets the value at a specified index. + *@param nIndex The index of the item to return. + *@returns The specified item, or NULL if the index was beyond the range + * of the list. + *@author Mike Buland + */ + virtual void *getAt( int nIndex ) = 0; + + /** Append the given data to the end of the list. This increases the + * size of the list by one. + *@param pData The data to append to the list. + *@author Mike Buland + */ + virtual void append( void *pData ) = 0; + + /** Inserts an item at the specified position in the list. The + * new item takes the index that you specify, and all other items + * are moved up one position. The size of the list is increased by + * one. + *@param pData The value to insert into the list. + *@param nPos Where to insert the data into the list. + *@author Mike Buland + */ + virtual void insertBefore( void *pData, int nPos = 0 ) = 0; + + /** Determines the size of the list, in elements. + *@returns The size of the list. + *@author Mike Buland + */ + virtual int getSize( ) = 0; + + /** Determines if the list is empty or not. + *@returns True if the list is empty, or false if the list has + * data in it (if the size is greater than zero). + *@author Mike Buland + */ + virtual bool isEmpty( ) = 0; + + /** Deletes an item at the specified index and moves all other + * values down one index. The size of the list is decreased by one. + *@param nIndex The index of the item to delete. + *@author Mike Buland + */ + virtual void deleteAt( int nIndex ) = 0; + + /** Completely empties the list, and sets the effective size to + * zero. + *@author Mike Buland + */ + virtual void empty() = 0; + + /** Sets the size of the list. This can be larger or smaller + * than what it was previously. If larger, new blank items will + * be added to the end of the list. If smaller than the old list + * items will be deleted from the end. + *@param nNewSize The new size of the list. + *@author Mike Buland + */ + virtual void setSize( int nNewSize ) = 0; + + /** Sets a member at a specified location to a new value. + * If the member being set is outside of the range of the + * current list it should be expanded. + *@param nIndex The zero-based index of the item to change. + *@param pData The new value for that index. + *@author Mike Buland + */ + virtual void setAt( int nIndex, void *pData ) = 0; + + /** Makes the List work like an array. Just say listObj[2] to get + * the third element. + *@param nIndex The index to access in the list. + *@returns A pointer to the data at element index. + *@author Mike Buland + */ + void *operator[]( int nIndex ) { return getAt( nIndex ); }; +}; + +#endif + 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 @@ +#include +#include +#include +#include "md5.h" + +// This is a fun macro that tells us where the length char goes after the data +// section in the padded data segment. It's short for OBfuscation LOCaction. +#define OBLOC(len) ((((len + 64) >> 9) << 4) + 14) +// This performs a wrapping bitwise shift, kinda' fun! + +#define bit_roll( num, cnt ) \ + (((num) << (cnt)) | (((num) >> (32 - (cnt))) & ~(-1<<(cnt)))) + +//#define md5_cmn( q, a, b, x, s, t ) (bit_roll((a + q + x + t), s) + b) + +// The following are handy wrappers for the cmn function +#define md5_ff( a, b, c, d, x, s, t ) \ + (md5_cmn((b & c) | ((~b) & d), a, b, x, s, t)) + +#define md5_gg( a, b, c, d, x, s, t ) \ + (md5_cmn((b & d) | (c & (~d)), a, b, x, s, t)) + +#define md5_hh( a, b, c, d, x, s, t ) \ + (md5_cmn(b ^ c ^ d, a, b, x, s, t)) + +#define md5_ii( a, b, c, d, x, s, t ) \ + (md5_cmn(c ^ (b | (~d)), a, b, x, s, t)) + +inline long md5_cmn( long q, long a, long b, long x, long s, long t ) +{ + return bit_roll((a + q + x + t), s) + b; +} + +md5::md5() +{ +} + +md5::~md5() +{ +} + +/* + * Calculate the MD5 of an array of little-endian words, and a bit length + */ +void md5::core_md5( long *x, long len, md5sum *output ) +{ + long a = 1732584193, olda; + long b = -271733879, oldb; + long c = -1732584194, oldc; + long d = 271733878, oldd; + + for( long i = 0; i < len; i += 16 ) + { + olda = a; + oldb = b; + oldc = c; + oldd = d; + + a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936); + d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586); + c = md5_ff(c, d, a, b, x[i+ 2], 17, 606105819); + b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330); + a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897); + d = md5_ff(d, a, b, c, x[i+ 5], 12, 1200080426); + c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341); + b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983); + a = md5_ff(a, b, c, d, x[i+ 8], 7 , 1770035416); + d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417); + c = md5_ff(c, d, a, b, x[i+10], 17, -42063); + b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162); + a = md5_ff(a, b, c, d, x[i+12], 7 , 1804603682); + d = md5_ff(d, a, b, c, x[i+13], 12, -40341101); + c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290); + b = md5_ff(b, c, d, a, x[i+15], 22, 1236535329); + + a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510); + d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632); + c = md5_gg(c, d, a, b, x[i+11], 14, 643717713); + b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302); + a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691); + d = md5_gg(d, a, b, c, x[i+10], 9 , 38016083); + c = md5_gg(c, d, a, b, x[i+15], 14, -660478335); + b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848); + a = md5_gg(a, b, c, d, x[i+ 9], 5 , 568446438); + d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690); + c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961); + b = md5_gg(b, c, d, a, x[i+ 8], 20, 1163531501); + a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467); + d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784); + c = md5_gg(c, d, a, b, x[i+ 7], 14, 1735328473); + b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734); + + a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558); + d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463); + c = md5_hh(c, d, a, b, x[i+11], 16, 1839030562); + b = md5_hh(b, c, d, a, x[i+14], 23, -35309556); + a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060); + d = md5_hh(d, a, b, c, x[i+ 4], 11, 1272893353); + c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632); + b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640); + a = md5_hh(a, b, c, d, x[i+13], 4 , 681279174); + d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222); + c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979); + b = md5_hh(b, c, d, a, x[i+ 6], 23, 76029189); + a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487); + d = md5_hh(d, a, b, c, x[i+12], 11, -421815835); + c = md5_hh(c, d, a, b, x[i+15], 16, 530742520); + b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651); + + a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844); + d = md5_ii(d, a, b, c, x[i+ 7], 10, 1126891415); + c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905); + b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055); + a = md5_ii(a, b, c, d, x[i+12], 6 , 1700485571); + d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606); + c = md5_ii(c, d, a, b, x[i+10], 15, -1051523); + b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799); + a = md5_ii(a, b, c, d, x[i+ 8], 6 , 1873313359); + d = md5_ii(d, a, b, c, x[i+15], 10, -30611744); + c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380); + b = md5_ii(b, c, d, a, x[i+13], 21, 1309151649); + a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070); + d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379); + c = md5_ii(c, d, a, b, x[i+ 2], 15, 718787259); + b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551); + + a = a + olda; + b = b + oldb; + c = c + oldc; + d = d + oldd; + } + + output->data[0] = a; + output->data[1] = b; + output->data[2] = c; + output->data[3] = d; + delete[] x; +} + +long *md5::c2l( const char *str, long len, long *nNewLen ) +{ + long len8 = len*8; + long mlen = OBLOC( len8 ); + long flen = (((mlen/16)+((mlen%16)?(1):(0))))*16; + long *aBin = new long[flen]; + memset( aBin, 0, flen*4 ); + + for( long i = 0; i < len8; i+=8 ) + { + aBin[i>>5] |= ((long)str[i/8]) << (i%32); + } + + aBin[len8 >> 5] |= 0x80 << ((len8) % 32); + aBin[OBLOC( len8 )] = len8; + + (*nNewLen) = flen; + + return aBin; +} + +void md5::l2hexstr( long *binarray, char *str ) +{ + static const char hex_tab[] = {"0123456789abcdef"}; + //static char str[33]; + + int k = 0; + for( int i = 0; i < 16; i++) + { + str[k++] = hex_tab[(binarray[i>>2] >> ((i%4)*8+4)) & 0xF]; + str[k++] = hex_tab[(binarray[i>>2] >> ((i%4)*8 )) & 0xF]; + } +} + +void md5::sumString( md5sum *pSum, const char *sStr ) +{ + sumData( pSum, sStr, strlen( sStr ) ); +} + +void md5::sumData( md5sum *pSum, const char *aData, long nLen ) +{ + long nNewLen; + long *aOb = c2l( aData, nLen, &nNewLen ); + core_md5( aOb, nNewLen, pSum ); +} + +void md5::sumToHex( md5sum *pSum, char *sHex ) +{ + l2hexstr( pSum->data, sHex ); +} + 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 @@ +#ifndef MD5_H +#define MD5_H + +/** + * Used to store an MD5 sum in a handy container. + */ +typedef struct +{ + /** The actual data-storage for an MD5 sum. */ + long data[4]; +} md5sum; + +/** + * Class for easily calculating MD5 sums of just about any data. + *@author Mike Buland + */ +class md5 +{ +public: + /** Build an MD5 sum builder. */ + md5(); + + /** Deconstruct */ + virtual ~md5(); + + /** + * Create a sum of a standard c string, null terminated. This is probably + * the easiest function to use. + *@param pSum The MD5 sum structure to fill up. + *@param sStr The null-terminated string to turn into an MD5 sum. + */ + void sumString( md5sum *pSum, const char *sStr ); + + /** + * Create a sum of an array of arbitrary data. This is the most handy for + * dealing with files and so on. + *@param pSum The MD5 sum structure to fill up. + *@param aData A pointer to the base of the data to sum. + *@param nLen The number of bytes to use in the sum. + */ + void sumData( md5sum *pSum, const char *aData, long nLen ); + + /** + * Convert an md5sum to standard hex representation. Make sure that sHex + * contains at least 17 characters of space. + *@param pSum The sum structure to convert to hex. + *@param sHex The string to store the hex value in. + */ + void sumToHex( md5sum *pSum, char *sHex ); + +private: + /** + * Do the bulk of the work of the md5 algorithm. + *@param x I'm not sure. I'll need to look it up. + *@param len The length of the data. + *@param output The sum structure to put the output in. + */ + void core_md5( long *x, long len, md5sum *output ); + + /** + * Convert an array of charaters to an array of longs in a very crafty way. + * This also applies standard MD5 obfuscation to the resulting array, and + * makes it fit within MD5 size constraints. + *@param str The data to convert. + *@param len The length of the data. + *@param nNewLen A pointer to a variable that will hold the new length of + * the resulting array of longs. + *@returns The newly obfuscated and resized long array. + */ + long *c2l( const char *str, long len, long *nNewLen ); + + /** + * Backend helper to convert an array of longs into a hex string. + *@param binarray The binary data to convert. + *@param str The string to store the hex string in. + */ + void l2hexstr( long *binarray, char *str ); + +}; + +#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 @@ +#include "multilog.h" +#include +#include +#include +#include + +#include "multilogchannel.h" + +MultiLog::MultiLog() +{ + lChannel = new LinkedList(); + rEntry = new RingList( 150 ); + nEntriesLost = 0; +} + +MultiLog::~MultiLog() +{ + int nMax = lChannel->getSize(); + for( int j = 0; j < nMax; j++ ) + { + ((MultiLogChannel *)lChannel->getAt(j))->closeLog(); + delete ((MultiLogChannel *)lChannel->getAt(j)); + } + delete lChannel; + + for( int j = 0; j < rEntry->getSize(); j++ ) + { + delete (LogEntry *)rEntry->getAt( j ); + } + delete rEntry; +} +/* +void MultiLog::Log( int nLevel, const char *lpFormat, ...) +{ + switch( nLevel ) + { + default: + break; + } + va_list ap; + va_start(ap, lpFormat); + + vprintf( lpFormat, ap ); + + va_end(ap); +}*/ + +void MultiLog::DetailLog( int nLevel, const char *lpFile, int nLine, const char *lpFunction, const char *lpFormat, ...) +{ + LogEntry *e = new LogEntry(); + + va_list ap; + va_start(ap, lpFormat); + char *text; + vasprintf( &text, lpFormat, ap ); + va_end(ap); + + time( &e->xTime ); + e->nLevel = nLevel; + e->nLine = nLine; + e->lpFile = new char[strlen(lpFile)+1]; + strcpy( e->lpFile, lpFile ); + e->lpText = new char[strlen(text)+1]; + strcpy( e->lpText, text ); + free( text ); + + append( e ); +} + +void MultiLog::append( LogEntry *pEntry ) +{ + rEntry->append( pEntry ); + if( rEntry->getPushBuf() ) + { + delete (LogEntry *)rEntry->getPushBuf(); + nEntriesLost++; + } + + for( int j = 0; j < lChannel->getSize(); j++ ) + { + ((MultiLogChannel *)lChannel->getAt( j ))->append( pEntry ); + } +} + +void MultiLog::addChannel( MultiLogChannel *pChannel ) +{ + lChannel->append( pChannel ); + + pChannel->openLog(); + + for( int j = 0; j < rEntry->getSize(); j++ ) + { + pChannel->append( (LogEntry *)rEntry->getAt( j ) ); + } +} + +MultiLog::LogEntry::~LogEntry() +{ + delete[] lpFile; + delete[] lpText; +} + 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 @@ +#ifndef MULTILOG_H +#define MULTILOG_H + +#include +#include +#include + +#include "ringlist.h" +#include "linkedlist.h" +#include "singleton.h" + +/** + * Calls the DetailLog function but includes pre-processor macros to fill in + * most of the fields for you. This makes your life a lot easier, and makes the + * log useful for system debugging as well as just letting people know what's + * going on. + *@param LEVEL The log level, comes from an enum in the MultiLog class. + *@param FORMAT The text to store in the log, using printf style formatting. + *@param ... Parameters to help format the text in the FROMAT param. + */ +#define LineLog( LEVEL, FORMAT, ...) DetailLog( LEVEL, __FILE__, __LINE__, __PRETTY_FUNCTION__, FORMAT, ##__VA_ARGS__ ) + +#define MultiLineLog( LEVEL, FORMAT, ...) MultiLog::getInstance().DetailLog( LEVEL, __FILE__, __LINE__, __PRETTY_FUNCTION__, FORMAT, ##__VA_ARGS__ ) + +/** MultiLog keeps track of logfile info in a myriad of varieties, and is + * easily configurable between them all. It allows output to the standard + * output, error output, files, networks, and streams, which includes memory + * buffers. + * MultiLog uses the singleton pattern to keep only a single instance of + * the log. Instead of instantiating a new copy, call the getLog method. + *@author Mike Buland + */ +class MultiLog : public Singleton +{ + friend class Singleton; +public: + /** + * Keeps track of a single log entry, in a standard format, that can be + * processed by any MultiLogChannel derrived class. + *@author Mike Buland + */ + typedef struct LogEntry + { + /** Safely delete a log entry. */ + virtual ~LogEntry(); + time_t xTime; /**< The time the log entry was made. */ + int nLevel; /**< The log-level of the entry. */ + char *lpFile; /**< The name of the file this entry came from. */ + int nLine; /**< The line number that this log came from. */ + char *lpText; /**< The text content of this log entry. */ + } LogEntry; + +protected: + /** + * Private constructor, this ensures that this is a singleton. + */ + MultiLog(); + + /** + * Destroy the multilog. + */ + virtual ~MultiLog(); + + /** + * Append a new logentry to the log list, possibly pushing an old entry off. + *@param pEntry The new entry to append. + */ + void append( LogEntry *pEntry ); + + /** + * The actual log entry storage mechanism. + */ + RingList *rEntry; + + /** + * The number of entries that have rolled off the end of the RingList. + */ + unsigned long nEntriesLost; + + /** + * A list of all channels that are registered with the MultiLog. + */ + LinkedList *lChannel; + +public: + + /** Sends info to the logfile. + *@param nLevel The type of data being logged (error, info, etc.) + *@param lpFormat The data to send to the log. + *@author Mike Buland + */ + //void Log( int nLevel, const char *lpFormat, ...); + + /** Sends info to the logfile with extra information, including the files + * that it was called from and the line in the code. Besides that, it's + * exactly the same as Log. Please use the LineLog macro to make DetailLog + * really easy to use. It operates exacly like Log, but inserts the + * builtin macros as the lpFile and nLine parameters. + *@param nLevel The type of data being logged (error, info, etc.) + *@param lpFile The name of the file that called the log function. + *@param nLine The line in the file that this log function was called from. + *@param lpFunction The name of the function that called the log function. + *@param lpFormat The data to send to the log. + *@author Mike Buland + */ + void DetailLog( int nLevel, const char *lpFile, int nLine, const char *lpFunction, const char *lpFormat, ...); + + /** + * Adds a logging channel to the MultiLog channel chain. Every added + * channel will automatically receive a complete log of everything that + * happened before the channel was added as well as all future messages. + *@param pChannel A pointer to the pre-contructed channel object to add. + */ + void addChannel( class MultiLogChannel *pChannel ); + + /** The various pre-defined levels available to use when logging. + * The person logging can make up their own, just make sure to remember + * which value is which (all levels are integers). + *@author Mike Buland + */ + enum Levels + { + LError, + LWarning, + LInfo, + LStatus + }; +}; + +#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 @@ +// +// C++ Implementation: multilogchannel +// +// Description: +// +// +// Author: Mike Buland , (C) 2005 +// +// Copyright: See COPYING file that comes with this distribution +// +// +#include "multilogchannel.h" + 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 @@ +#ifndef MULTILOGCHANNEL_H +#define MULTILOGCHANNEL_H + +#include "multilog.h" + +/** + * The baseclass for any MultiLog output channel. Any class that implements + * all of these functions can be put in the log chain and will be sent + * messages from active MultiLoggers. + *@author Mike Buland + */ +class MultiLogChannel +{ +public: + /** + * Deconstruct a MultiLogChannel. + */ + virtual ~MultiLogChannel() {}; + + /** + * Should perform any operations that need to take place in order to start + * the output of data into this channel. This will be called once by the + * MultiLog when the MultiLogChannel is registered. + *@returns True means that everything can go as planned. False means that + * the MultiLog should remove this channel from the list and delete it. + */ + virtual bool openLog() = 0; + + /** + * Should append a log entry to the long, by whatever means are necesarry. + *@param pEntry The LogEntry to append. + *@returns True means that everything can go as planned. False means that + * the MultiLog should remove this channel from the list and delete it. + */ + virtual bool append( MultiLog::LogEntry *pEntry ) = 0; + + /** + * Should perform any operations that need to take place in order to safely + * close and cleanup the log. + *@returns True means that everything can go as planned. False means that + * the MultiLog should remove this channel from the list and delete it. + */ + virtual bool closeLog() = 0; +}; + +#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 @@ +#include +#include +#include +#include +#include +#include +#include "multilogtext.h" +/* +bool fileexists( const char *sPath ) +{ + int nFileDesc = open( sPath, O_RDONLY ); + if( nFileDesc < 0 ) + { + return false; + } + else + { + close( nFileDesc ); + return true; + } +}*/ + +MultiLogText::MultiLogText( const char *sFileName, const char *lpFormat, bool bRotateLog, int nMaxLogs ) +{ + this->lpFormat = NULL; + /* + if( bRotateLog ) + { + if( fileexists( sFileName ) == false ) + { + return; + } + + int nLen = strlen( sFileName ); + char *buf = new char[nLen+6]; + sprintf( buf, "%s.", sFileName ); + + for( int j = 1; j < nMaxLogs; j++ ) + { + sprintf( &buf[nLen+1], "%d", j ); + if( !fileexists( buf ) ) + { + rename( sFileName, buf ); + break; + } + } + }*/ + + nFD = open( sFileName, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH ); + setLogFormat( lpFormat ); +} + +MultiLogText::MultiLogText( int nFileDesc, const char *lpFormat ) +{ + this->lpFormat = NULL; + nFD = nFileDesc; + setLogFormat( lpFormat ); +} + +MultiLogText::~MultiLogText() +{ + if( nFD != -1 ) + { + close( nFD ); + } + + delete[] lpFormat; +} + +bool MultiLogText::setLogFormat( const char *lpFormat ) +{ + char buf[200]; + int k = 0; + static char fmts[10][4]={ + {'y', 'd', '0', '1'}, + {'m', 'd', '0', '2'}, + {'d', 'd', '0', '3'}, + {'h', 'd', '0', '4'}, + {'M', 'd', '0', '5'}, + {'s', 'd', '0', '6'}, + {'l', 'd', '0', '7'}, + {'f', 's', '0', '8'}, + {'L', 'd', '0', '9'}, + {'t', 's', '1', '0'}, + }; + + for( int j = 0; lpFormat[j] != '\0'; j++ ) + { + if( lpFormat[j] == '%' ) + { + buf[k++] = '%'; + int nPlace = k++; + k++; + buf[k++] = '$'; + bool bDone = false; + for( j++; bDone == false; j++ ) + { + int l; + for( l = 0; l < 10; l++ ) + { + if( lpFormat[j] == fmts[l][0] ) + { + buf[nPlace] = fmts[l][2]; + buf[nPlace+1] = fmts[l][3]; + buf[k++] = fmts[l][1]; + bDone = true; + break; + } + } + if( l == 10 ) + { + buf[k++] = lpFormat[j]; + } + } + j--; + } + else + { + buf[k++] = lpFormat[j]; + } + } + buf[k++] = '\n'; + buf[k] = '\0'; + + if( this->lpFormat != NULL ) + { + delete[] this->lpFormat; + } + this->lpFormat = new char[k+1]; + strcpy( this->lpFormat, buf ); + + return true; +} + +bool MultiLogText::openLog() +{ + if( nFD == -1 ) + { + return false; + } + return true; +} + +bool MultiLogText::append( MultiLog::LogEntry *pEntry ) +{ + if( nFD == -1 ) + { + return false; + } + + char *line = NULL; + struct tm *pTime; + pTime = localtime( &pEntry->xTime ); + asprintf( + &line, + lpFormat, + pTime->tm_year+1900, + pTime->tm_mon+1, + pTime->tm_mday, + pTime->tm_hour, + pTime->tm_min, + pTime->tm_sec, + pEntry->nLevel, + pEntry->lpFile, + pEntry->nLine, + pEntry->lpText + ); + write( nFD, line, strlen(line) ); + free( line ); + + return true; +} + +bool MultiLogText::closeLog() +{ + if( nFD == -1 ) + { + return false; + } + // Don't close it if it's sdtout or errorout + if( nFD > 2 ) + { + close( nFD ); + } + nFD = -1; + return true; +} + 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 @@ +#ifndef MULTILOGTEXT_H +#define MULTILOGTEXT_H + +#include "multilogchannel.h" + +/** + * Simple MultiLogChannel that takes the logdata, formats it textually, and + * writes it to a text device, either a file or the screen, yay! This takes + * the place of the old standard logging facility. + * The entries in the format follow the standard printf % style, and are as + * follows: + *
    + *
  • %y - current year
  • + *
  • %m - current month
  • + *
  • %d - current day
  • + *
  • %h - current hour (24-hour format)
  • + *
  • %M - current minute
  • + *
  • %s - current seccond
  • + *
  • %l - Loglevel (numerical)
  • + *
  • %f - Filename
  • + *
  • %L - Line number
  • + *
  • %t - Full text of the log entry
  • + *
+ *@author Mike Buland + */ +class MultiLogText : public MultiLogChannel +{ +public: + /** + * Construct a MultiLogText object around a specific filename and format. + * The file named by sFileName will be opened for writting in text+append + * mode. No existing data will be destroyed. + *@param sFileName The file to output log-data to. + *@param lpFormat The format using the above specifications to be used for + * every log entry. + */ + MultiLogText( const char *sFileName, const char *lpFormat, bool bRotateLog=false, int nMaxLogs=0 ); + + /** + * Construct a MultiLogText object around a specific file and format. + * The file descriptor passed in should describe an already opened and set- + * up file or device. This could easily be a socket or stdout or stderr. + *@param nFileDesc The already opened descriptor to send data to. + *@param lpFormat The format using the above specifications to be used for + * every log entry. + */ + MultiLogText( int nFileDesc, const char *lpFormat ); + + /** + * Destroy the object. + */ + virtual ~MultiLogText(); + + bool openLog(); + bool append( MultiLog::LogEntry *pEntry ); + bool closeLog(); + + /** + * Change the log format on the fly. + *@param lpFormat The new format to use for all future log entries. + *@returns True if everything was fine, false for catastrophic failure. + */ + bool setLogFormat( const char *lpFormat ); + +private: + int nFD; /**< The file descriptor we're writing to. */ + char *lpFormat; /**< The format that we're using, converted for printf. */ +}; + +#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 @@ +#ifndef ORD_HASH_H +#define ORD_HASH_H + +#include "hash.h" +#include "tqsort.h" + +template, typename valuealloc = std::allocator, typename challoc = std::allocator > +class OrdHash : public Hash +{ +public: + OrdHash() : + bSorted( false ), + aData( NULL ) + { + } + + virtual ~OrdHash() + { + } + +protected: + virtual void invalidate() + { + bSorted = false; + delete[] aData; + aData = NULL; + } + + virtual void onInsert() + { + invalidate(); + } + + virtual void onUpdate() + { + invalidate(); + } + + virtual void onDelete() + { + invalidate(); + } + + virtual void onReHash() + { + invalidate(); + } + + virtual std::pair getAtPos( uint32_t nPos ) + { + return Hash::getAtPos( aData[nPos].nIndex ); + } + + virtual void buildIndex() + { + aData = new struct ind[this->nFilled]; + uint32_t k = 0; + for( uint32_t j = 0; j < this->nCapacity; j++ ) + { + if( this->isFilled( j ) ) + { + if( !this->isDeleted( j ) ) + { + aData[k].pVal = &(this->aValues[j]); + aData[k].nIndex = j; + k++; + } + } + } + + tqsort::ind, cmpfnc, value **>( aData, this->nFilled ); + + bSorted = true; + } + + virtual uint32_t getFirstPos( bool &bFinished ) + { + if( bSorted == false ) + buildIndex(); + + return 0; + } + + virtual uint32_t getNextPos( uint32_t nPos, bool &bFinished ) + { + if( nPos+1 >= this->nFilled ) + { + bFinished = true; + return 0; + } + return ++nPos; + } +public: + typedef struct ind + { + value *pVal; + uint32_t nIndex; + } ind; +private: + bool bSorted; + ind *aData; +}; + +#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 @@ +#include "paramproc.h" +#include + +#define ptrtype( iitype, iiname ) \ + ParamProc::ParamPtr::ParamPtr( iitype *iiname ) : \ + type( vt ##iiname ) { val.iiname = iiname; } + +ParamProc::ParamPtr::ParamPtr() +{ + val.str = NULL; + type = vtunset; +} + +ptrtype( std::string, str ); +ptrtype( uint64_t, uint64 ); +ptrtype( uint32_t, uint32 ); +ptrtype( uint16_t, uint16 ); +ptrtype( uint8_t, uint8 ); +ptrtype( int64_t, int64 ); +ptrtype( int32_t, int32 ); +ptrtype( int16_t, int16 ); +ptrtype( int8_t, int8 ); +ptrtype( float, float32 ); +ptrtype( double, float64 ); +ptrtype( long double, float96 ); +ptrtype( bool, bln ); + +ParamProc::ParamPtr &ParamProc::ParamPtr::operator=( ParamProc::ParamPtr &ptr ) +{ + val = ptr.val; + type = ptr.type; + + return *this; +} + +bool ParamProc::ParamPtr::isSet() +{ + return type != vtunset; +} + +ParamProc::ParamPtr &ParamProc::ParamPtr::operator=( const char *str ) +{ + if( !isSet() ) return *this; + switch( type ) + { + case vtstr: + (*val.str) = str; + break; + + case vtuint64: + (*val.uint64) = strtoull( str, NULL, 10 ); + break; + + case vtuint32: + (*val.uint32) = strtoul( str, NULL, 10 ); + break; + + case vtuint16: + (*val.uint16) = (uint16_t)strtoul( str, NULL, 10 ); + break; + + case vtuint8: + (*val.uint8) = (uint8_t)strtoul( str, NULL, 10 ); + break; + + case vtint64: + (*val.int64) = strtoll( str, NULL, 10 ); + break; + + case vtint32: + (*val.int32) = strtol( str, NULL, 10 ); + break; + + case vtint16: + (*val.int16) = (int16_t)strtol( str, NULL, 10 ); + break; + + case vtint8: + (*val.int8) = (int8_t)strtol( str, NULL, 10 ); + break; + + case vtfloat32: + (*val.float32) = strtof( str, NULL ); + break; + + case vtfloat64: + (*val.float64) = strtod( str, NULL ); + break; + + case vtfloat96: + (*val.float96) = strtold( str, NULL ); + break; + + case vtbln: + if( strcasecmp("yes", str ) == 0 || + strcasecmp("true", str ) == 0 ) + { + (*val.bln) = true; + } + else + { + (*val.bln) = false; + } + break; + } + + return *this; +} + +ParamProc::ParamProc() +{ +} + +ParamProc::~ParamProc() +{ + for( std::list::iterator i = lArg.begin(); + i != lArg.end(); i++ ) + { + delete *i; + } + + for( std::list::iterator i = lBan.begin(); + i != lBan.end(); i++ ) + { + delete *i; + } + +} +/* +void ParamProc::addParam( const char *lpWord, char cChar, Proc proc, ParamPtr val ) +{ + printf("Calling callback...\n"); + val = "Hello there, this is set in the ParamProc"; + (this->*proc)(); +}*/ + +void ParamProc::addParam( const char *lpWord, char cChar, Proc proc, + ParamPtr val, const char *lpDesc, const char *lpExtra, + const char *lpValue ) +{ + ArgSpec *as = new ArgSpec; + if( lpWord ) + as->sWord = lpWord; + + as->cChar = cChar; + as->proc = proc; + as->val = val; + if( lpDesc ) + as->sDesc = lpDesc; + if( lpExtra ) + as->sExtra = lpExtra; + if( lpValue ) + as->sValue = lpValue; + + lArg.push_back( as ); + + if( !lBan.empty() ) + { + if( lBan.back()->pBefore == NULL ) + lBan.back()->pBefore = as; + } +} + +void ParamProc::addParam( const char *lpWord, char cChar, Proc proc, + const char *lpDesc, const char *lpExtra, + const char *lpValue ) +{ + addParam( lpWord, cChar, proc, ParamPtr(), lpDesc, lpExtra, lpValue ); +} + +void ParamProc::addParam( const char *lpWord, char cChar, ParamPtr val, + const char *lpDesc, const char *lpExtra, + const char *lpValue ) +{ + addParam( lpWord, cChar, NULL, val, lpDesc, lpExtra, lpValue ); +} + +void ParamProc::addParam( const char *lpWord, Proc proc, ParamPtr val, + const char *lpDesc, const char *lpExtra, + const char *lpValue ) +{ + addParam( lpWord, '\0', proc, val, lpDesc, lpExtra, lpValue ); +} + +void ParamProc::addParam( const char *lpWord, Proc proc, + const char *lpDesc, const char *lpExtra, + const char *lpValue ) +{ + addParam( lpWord, '\0', proc, ParamPtr(), lpDesc, lpExtra, lpValue ); +} + +void ParamProc::addParam( const char *lpWord, ParamPtr val, + const char *lpDesc, const char *lpExtra, + const char *lpValue ) +{ + addParam( lpWord, '\0', NULL, val, lpDesc, lpExtra, lpValue ); +} + +void ParamProc::addParam( char cChar, Proc proc, ParamPtr val, + const char *lpDesc, const char *lpExtra, + const char *lpValue ) +{ + addParam( NULL, cChar, proc, val, lpDesc, lpExtra, lpValue ); +} + +void ParamProc::addParam( char cChar, Proc proc, + const char *lpDesc, const char *lpExtra, + const char *lpValue ) +{ + addParam( NULL, cChar, proc, ParamPtr(), lpDesc, lpExtra, lpValue ); +} + +void ParamProc::addParam( char cChar, ParamPtr val, + const char *lpDesc, const char *lpExtra, + const char *lpValue ) +{ + addParam( NULL, cChar, NULL, val, lpDesc, lpExtra, lpValue ); +} + +void ParamProc::process( int argc, char *argv[] ) +{ + for( int arg = 1; arg < argc; arg++ ) + { + //printf(":::%d:::%s\n", arg, argv[arg] ); + if( argv[arg][0] == '-' ) + { + if( argv[arg][1] == '-' ) + { + ArgSpec *s = checkWord( argv[arg]+2 ); + if( s ) + { + if( argv[arg][s->sWord.getLength()+2] == '=' ) + { + if( s->val.isSet() ) + { + if( s->sValue.getString() == NULL ) + { + s->val = argv[arg]+s->sWord.getLength()+3; + } + else + { + s->val = s->sValue.getString(); + } + } + if( s->proc ) + { + char **tmp = new char*[argc-arg]; + tmp[0] = argv[arg]+s->sWord.getLength()+3; + for( int k = 1; k < argc-arg; k++ ) + tmp[k] = argv[arg+k]; + int ret = (this->*s->proc)( argc-arg, tmp ); + if( ret > 0 ) + { + arg += ret-1; + } + delete tmp; + } + } + else + { + int add = 0; + if( s->val.isSet() ) + { + if( s->sValue.getString() == NULL ) + { + if( arg+1 >= argc ) + { + return; + } + s->val = argv[arg+1]; + add++; + } + else + { + s->val = s->sValue.getString(); + } + } + if( s->proc ) + { + int ret = (this->*s->proc)( + argc-arg-1, argv+arg+1 ); + + if( ret > add ) + add = 0; + else + add -= ret; + arg += ret; + } + arg += add; + } + continue; + } + else + { + unknownParam( argc-arg, argv+arg ); + } + } + else + { + for( int chr = 1; argv[arg][chr]; chr++ ) + { + ArgSpec *s = checkLetr( argv[arg][chr] ); + if( s ) + { + if( argv[arg][chr+1] != '\0' ) + { + bool bUsed = false; + if( s->val.isSet() ) + { + if( s->sValue.getString() == NULL ) + { + s->val = argv[arg]+chr+1; + bUsed = true; + } + else + { + s->val = s->sValue.getString(); + } + } + if( s->proc ) + { + char **tmp = new char*[argc-arg]; + tmp[0] = argv[arg]+chr+1; + for( int k = 1; k < argc-arg; k++ ) + tmp[k] = argv[arg+k]; + int ret = (this->*s->proc)( argc-arg, tmp ); + if( ret > 0 ) + { + arg += ret - 1; + delete tmp; + break; + } + delete tmp; + } + if( bUsed ) + { + break; + } + } + else + { + bool bUsed = false; + if( s->val.isSet() ) + { + if( s->sValue.getString() == NULL ) + { + s->val = argv[arg+1]; + bUsed = true; + } + else + { + s->val = s->sValue.getString(); + } + } + if( s->proc ) + { + int ret = (this->*s->proc)( + argc-arg-1, argv+arg+1 + ); + if( ret > 0 ) + { + arg += ret; + break; + } + } + if( bUsed ) + { + arg++; + break; + } + } + } + else + { + unknownParam( argc-arg, argv+arg ); + } + } + } + } + else + { + cmdParam( argc-arg, argv+arg ); + } + } +} + +ParamProc::ArgSpec *ParamProc::checkWord( const char *arg ) +{ + //printf("Checking \"%s\"...\n", arg ); + std::list::const_iterator i; + for( i = lArg.begin(); i != lArg.end(); i++ ) + { + if( (*i)->sWord.getString() == NULL ) + continue; + + if( !strcmp( (*i)->sWord, arg ) ) + return *i; + + if( (*i)->val.isSet() ) + { + if( !strncmp( (*i)->sWord, arg, (*i)->sWord.getLength() ) && + arg[(*i)->sWord.getLength()] == '=' ) + { + return *i; + } + } + } + + return NULL; +} + +ParamProc::ArgSpec *ParamProc::checkLetr( const char arg ) +{ + //printf("Checking \'%c\'...\n", arg ); + std::list::const_iterator i; + for( i = lArg.begin(); i != lArg.end(); i++ ) + { + if( (*i)->cChar == '\0' ) + continue; + + if( (*i)->cChar == arg ) + { + return *i; + } + } + + return NULL; +} + +int ParamProc::cmdParam( int argc, char *argv[] ) +{ + printf("Unhandled command parameter \"%s\" found!\n", argv[0] ); + return 0; +} + +int ParamProc::unknownParam( int argc, char *argv[] ) +{ + printf("Unknown parameter \"%s\" found!\n", argv[0] ); + return 0; +} + +int ParamProc::help( int argc, char *argv[] ) +{ + std::list::const_iterator b = lBan.begin(); + std::list::const_iterator i; + int len=0; + for( i = lArg.begin(); i != lArg.end(); i++ ) + { + if( len < (*i)->sWord.getLength() + (*i)->sExtra.getLength() ) + len = (*i)->sWord.getLength() + (*i)->sExtra.getLength(); + } + char fmt[10]; + sprintf( fmt, "%%-%ds ", len ); + + for( i = lArg.begin(); i != lArg.end(); i++ ) + { + if( b != lBan.end() ) + { + if( (*b)->pBefore == (*i) ) + { + printf( (*b)->sBanner.getString() ); + b++; + } + } + printf(" "); + if( (*i)->cChar ) + { + if( (*i)->sWord.getString() ) + { + printf("-%c, ", (*i)->cChar ); + } + else + { + printf("-%c ", (*i)->cChar ); + } + } + else + { + printf(" "); + } + if( (*i)->sWord.getString() ) + { + printf("--"); + std::string sTmp = (*i)->sWord.getString(); + if( (*i)->sExtra.getString() ) + sTmp += (*i)->sExtra.getString(); + printf( fmt, sTmp.c_str() ); + } + else + { + printf(" "); + printf(fmt, "" ); + } + printf("%s\n", (*i)->sDesc.getString() ); + } + if( b != lBan.end() ) + { + if( (*b)->pBefore == NULL ) + { + printf( (*b)->sBanner.getString() ); + } + } + + exit( 0 ); +} + +void ParamProc::addHelpBanner( const char *sHelpBanner ) +{ + Banner *pBan = new Banner; + pBan->sBanner = sHelpBanner; + pBan->pBefore = NULL; + lBan.push_back( pBan ); +} + 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 @@ +#ifndef PARAM_PROC_H +#define PARAM_PROC_H + +#include +#include +#include +#include "staticstring.h" + +class ParamProc +{ +public: + class ParamPtr + { + public: + ParamPtr(); + ParamPtr( std::string *str ); + ParamPtr( uint64_t *uint64 ); + ParamPtr( uint32_t *uint32 ); + ParamPtr( uint16_t *uint16 ); + ParamPtr( uint8_t *uint8 ); + ParamPtr( int64_t *int64 ); + ParamPtr( int32_t *int32 ); + ParamPtr( int16_t *int16 ); + ParamPtr( int8_t *int8 ); + ParamPtr( float *float32 ); + ParamPtr( double *float64 ); + ParamPtr( long double *float96 ); + ParamPtr( bool *bln ); + + enum + { + vtunset, + vtstr, + vtuint64, + vtuint32, + vtuint16, + vtuint8, + vtint64, + vtint32, + vtint16, + vtint8, + vtfloat32, + vtfloat64, + vtfloat96, + vtbln, + }; + ParamPtr &operator=( ParamPtr &ptr ); + ParamPtr &operator=( const char *str ); + + bool isSet(); + + private: + int type; + union + { + std::string *str; + uint64_t *uint64; + uint32_t *uint32; + uint16_t *uint16; + uint8_t *uint8; + int64_t *int64; + int32_t *int32; + int16_t *int16; + int8_t *int8; + float *float32; + double *float64; + long double *float96; + bool *bln; + } val; + }; + + typedef int (ParamProc::*Proc)( int, char *[] ); + + typedef struct ArgSpec + { + uint8_t nFlags; + StaticString sWord; + char cChar; + Proc proc; + ParamProc::ParamPtr val; + StaticString sExtra; + StaticString sDesc; + StaticString sValue; + } ArgSpec; + +public: + ParamProc(); + virtual ~ParamProc(); + + void addParam( const char *lpWord, char cChar, Proc proc, ParamPtr val, + const char *lpDesc=NULL, const char *lpExtra=NULL, + const char *lpValue=NULL + ); + void addParam( const char *lpWord, char cChar, Proc proc, + const char *lpDesc=NULL, const char *lpExtra=NULL, + const char *lpValue=NULL + ); + void addParam( const char *lpWord, char cChar, ParamPtr val, + const char *lpDesc=NULL, const char *lpExtra=NULL, + const char *lpValue=NULL + ); + + void addParam( const char *lpWord, Proc proc, ParamPtr val, + const char *lpDesc=NULL, const char *lpExtra=NULL, + const char *lpValue=NULL + ); + void addParam( const char *lpWord, Proc proc, + const char *lpDesc=NULL, const char *lpExtra=NULL, + const char *lpValue=NULL + ); + void addParam( const char *lpWord, ParamPtr val, + const char *lpDesc=NULL, const char *lpExtra=NULL, + const char *lpValue=NULL + ); + + void addParam( char cChar, Proc proc, ParamPtr val, + const char *lpDesc=NULL, const char *lpExtra=NULL, + const char *lpValue=NULL + ); + void addParam( char cChar, Proc proc, + const char *lpDesc=NULL, const char *lpExtra=NULL, + const char *lpValue=NULL + ); + void addParam( char cChar, ParamPtr val, + const char *lpDesc=NULL, const char *lpExtra=NULL, + const char *lpValue=NULL + ); + + void process( int argc, char *argv[] ); + void addHelpBanner( const char *sHelpBanner ); + +private: + ArgSpec *checkWord( const char *arg ); + ArgSpec *checkLetr( const char arg ); + +public: + virtual int cmdParam( int argc, char *argv[] ); + virtual int unknownParam( int argc, char *argv[] ); + virtual int help( int argc, char *argv[] ); + +private: + typedef struct Banner + { + StaticString sBanner; + ArgSpec *pBefore; + } Banner; + std::list lBan; + std::list lArg; +}; + +#define mkproc( cls ) static_cast(&cls) + +#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 @@ +#ifndef PLUGGER_H +#define PLUGGER_H + + +#include "hashtable.h" +#include "list" +#include "hashfunctionstring.h" +#include "hashfunctionint.h" +#include "dlfcn.h" +#include "exceptions.h" + +typedef struct PluginInfo +{ + const char *sID; + const char *sAuthor; + unsigned short nVersion; + unsigned short nRevision; + void *(*createPlugin)(); + void (*destroyPlugin)( void * ); +} PluginInfo; + +typedef struct PluginReg +{ + bool bBuiltin; + void *dlHandle; + PluginInfo *pInfo; +} PluginReg; + +#define PluginInterface( classname, baseclass, name, ver, rev ) \ +extern "C" { \ + baseclass *create ##classname() \ + { \ + return new classname(); \ + } \ + void destroy ##classname( baseclass *pCls ) \ + { \ + delete pCls; \ + } \ + PluginInfo classname = { \ + #classname, name, ver, rev, \ + create ##classname, destroy ##classname }; \ +} + +#define PluginInterface2( pluginname, classname, baseclass, name, ver, rev ) \ +extern "C" { \ + baseclass *create ##classname() \ + { \ + return new classname(); \ + } \ + void destroy ##classname( baseclass *pCls ) \ + { \ + delete pCls; \ + } \ + PluginInfo pluginname = { \ + #pluginname, name, ver, rev, \ + (void *(*)())(create ##classname), \ + (void (*)( void * ))(destroy ##classname) }; \ +} + +#define PluginInterface3( structname, pluginname, classname, baseclass, name, ver, rev ) \ +extern "C" { \ + baseclass *create ##classname() \ + { \ + return new classname(); \ + } \ + void destroy ##classname( baseclass *pCls ) \ + { \ + delete pCls; \ + } \ + PluginInfo structname = { \ + #pluginname, name, ver, rev, \ + (void *(*)())(create ##classname), \ + (void (*)( void * ))(destroy ##classname) }; \ +} + +template +class Plugger +{ +public: + +public: + Plugger() : + hPlugin( new HashFunctionString(), 11 ), + hObj( new HashFunctionInt(), 11 ) + { + } + + virtual ~Plugger() + { + void *pos = hObj.getFirstItemPos(); + while( (pos = hObj.getNextItemPos( pos )) ) + { + T *pPlug = (T *)hObj.getItemID( pos ); + PluginReg *pReg = (PluginReg *)hObj.getItemData( pos ); + pReg->pInfo->destroyPlugin( pPlug ); + } + + std::list::iterator i; + for( i = lPlugin.begin(); i != lPlugin.end(); i++ ) + { + if( (*i)->bBuiltin == false ) + { + dlclose( (*i)->dlHandle ); + } + delete (*i); + } + } + + void registerBuiltinPlugin( PluginInfo *pInfo ) + { + PluginReg *pReg = new PluginReg; + pReg->bBuiltin = true; + pReg->pInfo = pInfo; + lPlugin.insert( lPlugin.end(), pReg ); + hPlugin.insert( pInfo->sID, pReg ); + } + + void registerExternalPlugin( const char *sFName, const char *sPluginName ) + { + PluginReg *pReg = (PluginReg *)hPlugin[sPluginName]; + if( pReg != NULL ) + { + hPlugin.del( sPluginName ); + dlclose( pReg->dlHandle ); + delete pReg; + pReg = NULL; + } + + pReg = new PluginReg; + + pReg->bBuiltin = false; + pReg->dlHandle = dlopen( sFName, RTLD_NOW ); + if( pReg->dlHandle == NULL ) + { + throw PluginException( 1, "Error on %s: %s", sFName, dlerror() ); + } + pReg->pInfo = (PluginInfo *)dlsym( pReg->dlHandle, sPluginName ); + if( pReg->pInfo == NULL ) + { + throw PluginException( 2, "Error on %s: %s", sFName, dlerror() ); + } + hPlugin.insert( pReg->pInfo->sID, pReg ); + lPlugin.insert( lPlugin.end(), pReg ); + } + + T *instantiate( const char *lpName ) + { + PluginReg *pReg = (PluginReg *)hPlugin[lpName]; + if( pReg == NULL ) + return NULL; + + T *p = (T *)pReg->pInfo->createPlugin(); + hObj.insert( p, pReg ); + //printf("pReg: %08X, pPlug: %08X\n", pReg, p ); + + return p; + } + + bool hasPlugin( const char *lpName ) + { + if( hPlugin[lpName] == NULL ) + return false; + return true; + } + + void destroy( T *pPlug ) + { + PluginReg *pReg = (PluginReg *)hObj[pPlug]; + //printf("pReg: %08X, pPlug: %08X\n", pReg, pPlug ); + if( pReg == NULL ) + return; + + pReg->pInfo->destroyPlugin( pPlug ); + + hObj.del( pPlug ); + } + + void unloadAll() + { + std::list::iterator i; + for( i = lPlugin.begin(); i != lPlugin.end(); i++ ) + { + if( (*i)->bBuiltin == false ) + { + dlclose( (*i)->dlHandle ); + } + delete (*i); + } + hPlugin.clear(); + } + +private: + std::list lPlugin; + HashTable hPlugin; + HashTable hObj; +}; + +#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 @@ +#include "pqueue.h" + +PQueue::PQueue( int nNewNumQueues ) +{ + nNumQueues = nNewNumQueues; + aQueue = new Queue[nNumQueues]; +} + +PQueue::~PQueue() +{ + delete[] aQueue; +} + +void PQueue::enqueue( void *pData, int nQueueLevel ) +{ + if( nQueueLevel < 0 || nQueueLevel >= nNumQueues ) + return; + + aQueue[nQueueLevel].enqueue( pData ); +} + +void *PQueue::dequeue() +{ + for( int j = 0; j < nNumQueues; j++ ) + { + if( aQueue[j].isEmpty() == false ) + { + return aQueue[j].dequeue(); + } + } + + return NULL; +} 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 @@ +#ifndef PQUEUE_H +#define PQUEUE_H + +#include "queue.h" + +/** Priority queue. This is just like a queue, but something with a higher + * priority will always come off the queue before something with a lower + * priority, even if it's added after. Otherwise works just like a queue. + *@author Mike Buland + */ +class PQueue +{ +public: + /** Create a queue with any number of different priorities. + *@param nNewNumQueues The number of queues, the default is 3 + */ + PQueue( int nNewNumQueues=3 ); + + /** + * Cleanup all contained queues. + */ + virtual ~PQueue(); + + /** Add a new item to the queue at the specified priority. A lower + * number means a higher priority! + *@param pData A pointer to the data to add to the queue + *@param nQueueLevel The priority to set the new data to + */ + void enqueue( void *pData, int nQueueLevel ); + + /** Pull the next item off the queue, high priority first. + *@returns A pointer to the data that was next in the priority queue + */ + void *dequeue(); + +private: + /** + * The queues we use for real data storage. + */ + Queue *aQueue; + + /** + * The number of priorities or queus that we need. + */ + int nNumQueues; +}; + +#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 @@ +#include +#include "programchain.h" + +ProgramChain::ProgramChain() : + xLog( MultiLog::getInstance() ) +{ + xLog.LineLog( MultiLog::LStatus, "Program Chain Initialized." ); +} + +ProgramChain::~ProgramChain() +{ +} + +bool ProgramChain::addLink( ProgramLink *pLink ) +{ + if( pLink->init() == false ) + { + emergencyShutdown(); + return false; + } + + lLink.append( pLink ); + + pLink->setChain( this ); + + return true; +} + +ProgramLink *ProgramChain::getLink( const char *lpName ) +{ + char a; + a = lpName[0]; + return NULL; +} + +ProgramLink *ProgramChain::getBaseLink() +{ + return NULL; +} + +bool ProgramChain::execChainOnce() +{ + int nLen = lLink.getSize(); + for( int j = 0; j < nLen; j++ ) + { + if( ((ProgramLink *)lLink[j])->timeSlice() == false ) + { + xLog.LineLog( MultiLog::LInfo, "Shutting down due to signal from link #%d", j ); + emergencyShutdown(); + return false; + } + } + + return true; +} + +bool ProgramChain::enterChainLoop() +{ + for(;;) + { + if( execChainOnce() == false ) + { + return false; + } + } + + return true; +} + +void ProgramChain::emergencyShutdown() +{ + int nLen = lLink.getSize(); + for( int j = 0; j < nLen; j++ ) + { + ((ProgramLink *)lLink[j])->deInit(); + delete (ProgramLink *)lLink[j]; + } + lLink.empty(); +} + +LinkMessage *ProgramChain::broadcastIRM( LinkMessage *pMsgOut, ProgramLink *pSender ) +{ + int nLen = lLink.getSize(); + for( int j = 0; j < nLen; j++ ) + { + LinkMessage *pMsg = ((ProgramLink *)lLink[j])->processIRM( pMsgOut ); + if( pMsg != NULL ) + { + delete pMsgOut; + return pMsg; + } + } + + delete pMsgOut; + return NULL; +} 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 @@ +#ifndef PROGRAMCHAIN_H +#define PROGRAMCHAIN_H + +#include "linkedlist.h" +#include "multilog.h" +#include "programlink.h" + +/** + * The Program Chain links together program "chunks" to more easily facilitate + * a generalized program loop with modular extensions. + *@author Mike Buland + */ +class ProgramChain +{ +public: + /** + * Construct an empty chain. + */ + ProgramChain(); + + /** + * Destroy your chain. + */ + virtual ~ProgramChain(); + + /** + * Adds a link to the end of the chain. + *@param pLink A pointer to the link to add to the chain. + *@returns True if adding the link was successful, otherwise false + *@author Mike Buland + */ + bool addLink( ProgramLink *pLink ); + + /** + * Gets a link by name. + *@param lpName The name of the link you're looking for. Every link has a + * name, apparently. + *@returns A pointer to the specified ProgramLink, or NULL if none were + * found matching your criteria. + *@author Mike Buland + */ + class ProgramLink *getLink( const char *lpName ); + + /** + * Gets the very first link in the chain. + *@returns A pointer to the first link in the chain. + *@author Mike Buland + */ + class ProgramLink *getBaseLink(); + + /** + * Runs through the chain once. Useful if you want to have more control + * over the operation of the chain. + *@returns true if every link returned true. If at least one link returns + * false, then returns false. + *@author Mike Buland + */ + bool execChainOnce(); + + /** + * Enters the master chain loop, looping over the entire chain and + * executing every link's TimeSlice routine in order, over and over, until + * a link returns a false value. + *@returns False, always. It returns true unless a link returned false, + * but loops until a link does return false. + *@author Mike Buland + **/ + bool enterChainLoop(); + + /** + * Broadcasts an Immediate Response Message to all active links, save the + * sender. Whatever link first responds with a non-null response message + * will have it's messages sent back to the broadcasting link as the returns + * of this function call. Therefore it is very important that all message + * processing code is handled in a fairly timely fasion. + *@param pMsgOut The message to broadcast in hopes of a response. + *@param pSender The message that sent out the message and doesn't want to + * receive it's own message. This should always just be "this". + *@returns The message that was returned by the first link to return a + * non-null response. If all messages return null responses then this also + * returns null. Please note that whoever calls this will be responsible + * for deleting the message returned by it, if non-null. + */ + class LinkMessage *broadcastIRM( LinkMessage *pMsgOut, ProgramLink *pSender ); + +private: + /** + * Shuts down all operation no matter what point in the operation we were. + */ + void emergencyShutdown(); + MultiLog &xLog; /**< A reference to the log. */ + LinkedList lLink; /**< The linked list that contains all of the links. */ +}; + +#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 @@ +#include "programlink.h" +#include "programchain.h" + +ProgramLink::ProgramLink() +{ +} + +ProgramLink::~ProgramLink() +{ +} + +LinkMessage *ProgramLink::sendIRM( LinkMessage *pMsgOut ) +{ + return pChain->broadcastIRM( pMsgOut, this ); +} + +void ProgramLink::setChain( ProgramChain *pNewChain ) +{ + pChain = pNewChain; +} + +/* +void ProgramLink::postMessage( LinkMessage *pMsg, int nLvl ) +{ + if( nLvl == msgToChain ) + { + qMsgToChain.enqueue( pMsg ); + } + else if( nLvl == msgToLink ) + { + qMsgToLink.enqueue( pMsg ); + } + else + { + // ERROR! + } +} + +LinkMessage *ProgramLink::getMessage( int nLvl ) +{ + if( nLvl == msgToChain ) + { + return (LinkMessage *)qMsgToChain.dequeue(); + } + else if( nLvl == msgToLink ) + { + return (LinkMessage *)qMsgToLink.dequeue(); + } + else + { + // ERROR! + } +} +*/ 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 @@ +#ifndef PROGRAMLINK_H +#define PROGRAMLINK_H + +class ProgramLink; +#include "queue.h" +#include "linkmessage.h" +#include "programchain.h" + +/** + * Program Link is the base class for any object that will be a piece of the + * main program chain loop. + *@author Mike Buland + */ +class ProgramLink +{ +friend class ProgramChain; +public: + /** + * Construct a program link. + */ + ProgramLink(); + + /** + * Deconstruct. + */ + virtual ~ProgramLink(); + + /** + * Initialization code required for a link that wasn't performed in the + * constructor. + *@returns true if initialization was successful. A false value will halt + * the chain. + */ + virtual bool init()=0; + + /** + * DeInitialization code that should happen, but doesn't belong in the + * destructor. + *@returns true means everything worked, false means failure, but is + * meaningless. + */ + virtual bool deInit()=0; + + /** + * Executed once per link per chain pass. Contains the guts of the program. + *@returns true if everything went well. A false value will halt the chain. + */ + virtual bool timeSlice()=0; + + /** + * This must be handled in order to process Instant Response Messages. + * This function should return null on all messages that it doesn't + * understand how to handle, and construct new messages to return to sender + * in the cases where it does understand. + *@param pMsgIn The message that must be processed. + *@returns Either a new message in cases where a response is required, + * or null if nothing needs to be done by this link. + */ + virtual LinkMessage *processIRM( LinkMessage *pMsgIn ) = 0; + + /** + * Broadcast a LinkMessage to all other links in the system. Each other + * link will get a call of their processIRM function. If the message gets + * a response then you will regain control immediately, otherwise the system + * will give all other Links a chance to respond before returning NULL. + *@param pMsgOut The message to broadcast. + *@returns The message response, or NULL if no Link understood your message. + */ + LinkMessage *sendIRM( LinkMessage *pMsgOut ); + +private: + /** + * Set which chain we're assosiated with. This is how IRM messages make + * it out to the rest of the world. + *@param pNewChain A pointer to the containing program chain. + */ + void setChain( class ProgramChain *pNewChain ); + + /** + * The pointer to the containing chain. + */ + class ProgramChain *pChain; +/* + void postMessage( LinkMessage *pMsg, int nLvl ); + LinkMessage *getMessage( int nLvl ); + + enum + { + msgToChain, + msgToLink + }; + +private: + Queue qMsgToChain; + Queue qMsgToLink; +*/ +}; + +#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 @@ +#include "protocol.h" + +Protocol::Protocol() +{ + pConnection = NULL; +} + +Protocol::~Protocol() +{ +} + +void Protocol::setConnection( Connection *pNewConnection ) +{ + pConnection = pNewConnection; +} + +Connection *Protocol::getConnection() +{ + return pConnection; +} 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 @@ +#ifndef PROTOCOL_H +#define PROTOCOL_H + +#include "connection.h" + +/** This is the template for a class that handles specialized input and output + * to connections of different types with different protocols. + *@author Mike Buland + */ +class Protocol +{ +public: + /** Constructor */ + Protocol(); + /** Deconstructor */ + virtual ~Protocol(); + + /** + * Function is called every time there is new data on the line. This is + * called directly from the Connection class to process data. This is not + * called whever there is pending data on the input, but every time new data + * is added to the input buffer. + *@returns True if processing went alright, false if something went wrong, + * I suppose. In truth this value is thrown away right now. + *@todo Either make a return value of false mean something, or make these + * void. + */ + virtual bool onNewData()=0; + + /** + * Function is called when there is a new connection. This should only + * happen once per Protocol object, but gives each protocol object a + * chance to perform connection handshaking and initialization at a point + * where they know that they have a handle to an active Connection. + *@returns See onNewData + */ + virtual bool onNewConnection()=0; + + virtual void onNewClientConnection(){}; + + virtual void poll(){}; + + /** + * Sets the Protocol's Connection object. This is rather important, and + * handled usually by the ConnectionManager. + *@param pNewConnection The Connection object that this protocol will use to + * deal with the outside world. + */ + void setConnection( class Connection *pNewConnection ); + + /** + * Get a pointer to this object's Connection object, or NULL if one was + * never set. If used with the ConnectionManager that should never happen. + *@returns A pointer to the active Connection. + */ + Connection *getConnection(); + +private: + class Connection *pConnection; /**< The pointer to the Connection. */ +}; + +#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 @@ +#include "protocoltelnet.h" +#include + +ProtocolTelnet::ProtocolTelnet() +{ + nTermType = termUnInited; + bEchoOn = true; +} + +ProtocolTelnet::~ProtocolTelnet() +{ +} + +bool ProtocolTelnet::onNewConnection() +{ + Connection *pCon = getConnection(); + + pCon->appendOutput( (char)IAC ); + pCon->appendOutput( (char)WILL ); + pCon->appendOutput( (char)SUPPRESSGA ); + + pCon->appendOutput( (char)IAC ); + pCon->appendOutput( (char)DO ); + pCon->appendOutput( (char)SUPPRESSGA ); + + pCon->appendOutput( (char)IAC ); + pCon->appendOutput( (char)DONT ); + pCon->appendOutput( (char)TERMTYPE ); + +// pCon->appendOutput( IAC ); +// pCon->appendOutput( SB ); +// pCon->appendOutput( TERMTYPE ); +// pCon->appendOutput( 1 ); +// pCon->appendOutput( IAC ); +// pCon->appendOutput( SE ); + + pCon->appendOutput( (char)IAC ); + pCon->appendOutput( (char)DONT ); + pCon->appendOutput( (char)ECHO ); + + pCon->appendOutput( (char)IAC ); + pCon->appendOutput( (char)WILL ); + pCon->appendOutput( (char)ECHO ); + +// 255(IAC),251(WILL),3 + return true; +} + +bool ProtocolTelnet::onNewData() +{ + Connection *pCon = getConnection(); + if( !pCon->hasInput() ) + { + return true; + } + + int nInSize = pCon->getInputAmnt(); + char *lpInStr = (char *)pCon->getInput(); + + // Here we interpret the basic commands and un-encapsulate them, so to + // speak. We'll allow this, even if the terminal is in raw mode, we + // just won't send anything in response... + for( int j = 0; j < nInSize; j++ ) + { + switch( (unsigned char)lpInStr[j] ) + { + case '\r': + fbEdited.appendData('\n'); + if( bEchoOn ) pCon->appendOutput("\n\r"); + break; + + case '\n': + break; + + case '\177': // backspace + if( fbEdited.getLength() > 0 ) + { + fbEdited.usedData( -1 ); // Delete one char from the end + if( bEchoOn ) pCon->appendOutput(ESC "[D"); // Move the cursor back one + if( bEchoOn ) pCon->appendOutput(ESC "[P"); // Delete one character + } + break; + + case '\x1B': // escape sequence + if( (unsigned char)lpInStr[j+1] == '[' ) + { + switch( (unsigned char)lpInStr[j+2] ) + { + case 'A': // Up + break; + + case 'B': // Down + break; + + case 'C': // Right + break; + + case 'D': // Left + break; + } + j+=2; + } + break; + + case 0: // NOP: No operation + break; + + case IAC: // IAC: Interpret as command + switch( lpInStr[j+1] ) + { + case SE: // SE: End of subnegotiation parameters. + break; + + case NOP: // NOP: No operation + break; + + 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. + break; + + case BRK: // BRK: Break. Indicates that the "break" or "attention" key was hit. + break; + + case IP: // IP: Suspend, interrupt or abort the process to which the NVT is connected. + break; + + case AO: // AO: Abort output. Allows the current process to run to completion but do not send its output to the user. + break; + + case AYT: // AYT: Are you there. Send back to the NVT some visible evidence that the AYT was received. + break; + + case EC: // EC: Erase character. The receiver should delete the last preceding undeleted character from the data stream. + break; + + case EL: // EL: Erase line. Delete characters from the data stream back to but not including the previous CRLF. + break; + + case GA: // GA: Go ahead. Used, under certain circumstances, to tell the other end that it can transmit. + break; + + case SB: // SB: Subnegotiation of the indicated option follows. + switch( lpInStr[j+2] ) + { + case TERMTYPE: + if( lpInStr[j+3] == 0 ) + { + for( int k = 0; j+4+k < nInSize; k++ ) + { + if( (unsigned char)lpInStr[j+4+k] == IAC && + (unsigned char)lpInStr[j+5+k] == SE ) + { + lpInStr[j+4+k] = 0; + //@TODO: Do something with the term type... + printf("Term type: %s\n", &lpInStr[j+4] ); + j += 5+k; + } + } + } + else + { + } + break; + + default: + //printf("unknown subnegotiation parameters! (%d)\n", lpInStr[j+2] ); + break; + } + break; + + case WILL: // WILL: Indicates the desire to begin performing + switch( lpInStr[j+2] ) + { + case SUPPRESSGA: + j += 2; +// pCon->usedInput( 3 ); + break; + + case TERMTYPE: + j += 2; +// pCon->usedInput( 3 ); + break; + + case ECHO: + j += 2; +// pCon->usedInput( 3 ); + break; + + case NAWS: + default: + pCon->appendOutput( (char)ESC[0] ); + pCon->appendOutput( (char)DONT ); + pCon->appendOutput( lpInStr[j+2] ); + //printf("unknown will command used! (%d)\n", lpInStr[j+2] ); + j += 2; + break; + } + break; + + case WONT: // WONT: Indicates the refusal to perform + switch( lpInStr[j+2] ) + { + case ECHO: + j += 2; +// pCon->usedInput( 3 ); + break; + + default: + //printf("unknown wont command used! (%d)\n", lpInStr[j+2] ); + j += 2; + break; + } + break; + + case DO: // DO: Indicates the request that the other party perform + switch( lpInStr[j+2] ) + { + case ECHO: + j += 2; + break; + + case SUPPRESSGA: + j += 2; + break; + + default: + pCon->appendOutput( (char)ESC[0] ); + pCon->appendOutput( (char)DONT ); + pCon->appendOutput( lpInStr[j+2] ); + //printf("unknown do command used! (%d)\n", lpInStr[j+2] ); + j += 2; + break; + } +// pCon->usedInput( 3 ); + break; + + case DONT: // DONT: Indicates the demand that the other party stop performing + switch( lpInStr[j+2] ) + { + case ECHO: + j += 2; +// pCon->usedInput( 3 ); + break; + + default: + printf("unknown dont command used! (%d)\n", lpInStr[j+2] ); + j += 2; + break; + } + break; + } + break; + + default: + fbEdited.appendData( lpInStr[j] ); + if( bEchoOn ) pCon->appendOutput( lpInStr[j] ); + break; + } + } + + pCon->usedInput( pCon->getInputAmnt() ); + + return true; +} + +char *ProtocolTelnet::getLine( bool bFullOnly ) +{ + int i = fbEdited.findChar('\n'); + + if( i < 0 ) + { + if( bFullOnly == false ) + { + i = fbEdited.getLength(); + } + else + { + return NULL; + } + } + + char *lpStr = new char[i+1]; + strncpy( lpStr, fbEdited.getData(), i ); + lpStr[i] = '\0'; + + fbEdited.usedData( i+1 ); + + return lpStr; +} + +char *ProtocolTelnet::peekLine( bool bFullOnly ) +{ + int i = fbEdited.findChar('\n'); + + if( i < 0 ) + { + if( bFullOnly == false ) + { + i = fbEdited.getLength(); + } + else + { + return NULL; + } + } + + char *lpStr = new char[i+1]; + strncpy( lpStr, fbEdited.getData(), i ); + lpStr[i] = '\0'; + + return lpStr; +} + +void ProtocolTelnet::setEcho( bool bEchoOn ) +{ + this->bEchoOn = bEchoOn; +} 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 @@ +#ifndef PROTOCOLTELNET_H +#define PROTOCOLTELNET_H + +#include "protocol.h" +#include "flexbuf.h" + +#define ESC "\x1B" /**< A telnet escape code. */ + +/** Handles all specialized protocol actions related to the telnet protocol. + * This includes setting modes, non-scrollable regions, and so on. + *@author Mike Buland + */ +class ProtocolTelnet : public Protocol +{ +public: + ProtocolTelnet(); + virtual ~ProtocolTelnet(); + + bool onNewData(); + bool onNewConnection(); + + char *getLine( bool bFullOnly = true ); + char *peekLine( bool bFullOnly = true ); + + void setEcho( bool bEchoOn = true ); + + enum + { + termUnInited, + termRaw, + termUnknown, + termVT220, + termXTerm + }; + + enum + { + SE = 240, // SE: End of subnegotiation parameters. + NOP = 241, // NOP: No operation + 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. + BRK = 243, // BRK: Break. Indicates that the "break" or "attention" key was hit. + IP = 244, // IP: Suspend, interrupt or abort the process to which the NVT is connected. + AO = 245, // AO: Abort output. Allows the current process to run to completion but do not send its output to the user. + AYT = 246, // AYT: Are you there. Send back to the NVT some visible evidence that the AYT was received. + EC = 247, // EC: Erase character. The receiver should delete the last preceding undeleted character from the data stream. + EL = 248, // EL: Erase line. Delete characters from the data stream back to but not including the previous CRLF. + GA = 249, // GA: Go ahead. Used, under certain circumstances, to tell the other end that it can transmit. + SB = 250, // SB: Subnegotiation of the indicated option follows. + WILL = 251, // WILL: Indicates the desire to begin performing, or confirmation that you are now performing, the indicated option. + WONT = 252, // WONT: Indicates the refusal to perform, or continue performing, the indicated option. + 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. + 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. + IAC = 255 // IAC: Interpret as command + }; + + enum + { + ECHO = 1, // Explain who'll echo + SUPPRESSGA = 3, // Suppress Go Ahead + TERMTYPE = 24, // Terminal Type + NAWS = 31, // Window size + TERMSPEED = 32, // Terminal Speed + LINEMODE = 34 // Linemode + }; + +private: + int nTermType; + + int nTermWidth; + int nTermHeight; + + FlexBuf fbEdited; + + bool bEchoOn; +}; + +#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 @@ +#include "queue.h" + +void Queue::enqueue( void *data ) +{ + lQueueData.append( data ); +} + +void *Queue::dequeue() +{ + void *dat = lQueueData[0]; + if( dat != NULL ) + { + lQueueData.deleteAt( 0 ); + } + return dat; +} + +bool Queue::isEmpty() +{ + return lQueueData.isEmpty(); +} + +void Queue::empty() +{ + lQueueData.empty(); +} 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 @@ +#ifndef QUEUE_H +#define QUEUE_H +#include "linkedlist.h" + +/** + * An ultra-simple queue implementation. It just uses a linked list as it's + * container so we don't have to worry about anything! + *@author Mike Buland + */ +class Queue +{ +public: + /** + * Puts a new item at the end of the queue. + *@param data A new value to put at the end of the queue. + */ + void enqueue( void *data ); + + /** + * Gets the begining item of the queue off and returns it. + *@returns The value at the front of the queue. + */ + void *dequeue(); + + /** + * Checks if the queueu is empty. + *@returns True if the queueu is empty, and false if it has things in it. + */ + bool isEmpty(); + + /** + * Empty the queue. + */ + void empty(); + + /** + * Get a pointer to the internal list object. + *@returns A pointer to the internal list object. + */ + LinkedList *getList() { return &lQueueData; }; + +private: + LinkedList lQueueData; /**< Where all of the real data is stored. */ +}; +#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 @@ +// +// C++ Implementation: ringlist +// +// Description: +// +// +// Author: Mike Buland , (C) 2005 +// +// Copyright: See COPYING file that comes with this distribution +// +// +#include + +#include "ringlist.h" + +RingList::RingList( int nInitSize ) + : List() +{ + nFirstIndex = 0; + nRealLength = nInitSize; + nDataLength = 0; + apData = new void*[nInitSize]; + pPushBuf = NULL; +} + +RingList::~RingList() +{ + delete[] apData; +} + +void *RingList::getAt( int nIndex ) +{ + if( nIndex < 0 || nIndex >= nDataLength ) + { + return NULL; + } + + return apData[(nFirstIndex+nIndex)%nRealLength]; +} + +void RingList::append( void *pData ) +{ + int nIndex = (nFirstIndex+nDataLength)%nRealLength; + + pPushBuf = apData[nIndex]; + apData[nIndex] = pData; + + if( nDataLength == nRealLength ) + { + nFirstIndex = (nFirstIndex+1)%nRealLength; + } + else + { + nDataLength++; + // We really didn't need it this time... + pPushBuf = NULL; + } +} + +void RingList::insertBefore( void *pData, int nPos ) +{ + // Not implemented right now, don't even try it! +} + +int RingList::getSize() +{ + return nDataLength; +} + +bool RingList::isEmpty() +{ + return nDataLength==0; +} + +void RingList::deleteAt( int nIndex ) +{ + // Also not implemented yet +} + +void RingList::empty() +{ + nFirstIndex = 0; + nDataLength = 0; +} + +void RingList::setSize( int nNewSize ) +{ + if( apData ) + { + delete[] apData; + } + nFirstIndex = 0; + nRealLength = nNewSize; + nDataLength = 0; + apData = new void*[nNewSize]; +} + +void RingList::setAt( int nIndex, void *pData ) +{ + apData[(nIndex+nFirstIndex)%nRealLength] = pData; +} + +void *RingList::getPushBuf() +{ + return pPushBuf; +} 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 @@ +#ifndef RINGLIST_H +#define RINGLIST_H + +#include "list.h" + +/** + * A RingList or Ring Buffer implementation. This is a list that never grows in + * size once it is created, but instead once it is full new items added to the + * RingList replace the oldest items and the zero-index is virtually shifted. + * Since no data is actually moved when zero-index moves, this is very + * efficient. + *
+ * The items removed are not actually deleted by the RingList, so instead they + * are first moved into a temporary "Push Buffer" that can be accessed so that + * elements pushed off the edge of the RingList can be accessed for cleanup. + *@author Mike Buland + */ +class RingList : public List +{ +public: + /** + * Construct a RingList with a fixed initial size. This size never changes + * unless setSize is called later during normal operation. + *@param nInitSize The number of elements to allocate. + */ + RingList( int nInitSize ); + + /** + * Clean up the data structures, but not the contained elements. + */ + virtual ~RingList(); + + /** + * Get an element at the specified index. + *@param nIndex The index of the element to retreive. + *@returns A pointer to the requested element, or NULL if the element is + * not found or not initialized yet. + */ + void *getAt( int nIndex ); + + /** + * Append an element to the end of the list, overwriting the begining if + * necesarry. + *@param pData The pointer to append to the RingList. + */ + void append( void *pData ); + + /** + * Insert an element before another in the RingList, pushing all after it + * down the list. + *@param pData The data to insert. + *@param nPos The position that new the element should occupy in the list. + */ + void insertBefore( void *pData, int nPos = 0 ); + + /** + * Get the size of the array. + */ + int getSize(); + + /** + * Is the RingList empty? + *@returns True if it is empty, false otherwise. + */ + bool isEmpty(); + + /** + * Delete an element in the list, moving all later elements down one index. + *@param nIndex The index of the element to delete. + */ + void deleteAt( int nIndex ); + + /** + * Remove all elements from the RingList. + */ + void empty(); + + /** + * Set a new size for the RingList. Be careful with this one, if shrinking + * this may quietly create a memory leak. + *@param nNewSize The new size to set the RingList to. + *@todo Either fix this memory leak somehow or remove this function. + */ + void setSize( int nNewSize ); + + /** + * Set a specific element to a new value. + *@param nIndex The zero-based index to change the value of. + *@param pData The data to put at the location specified by nIndex. + */ + void setAt( int nIndex, void *pData ); + + /** + * Retrieve the contents of the push buffer. This is the data that is + * pushed off the end of the array if you append data and the list is full. + * This should be checked after every append operation to be sure there + * isn't anything that needs deleting. + *@returns The last value pushed off the RingList, or NULL if nothing was + * pushed off. + */ + void *getPushBuf(); + +private: + int nFirstIndex; /**< The index to be translated as zero. */ + int nRealLength; /**< The Amount of storage space available. */ + int nDataLength; /**< The number of elements filled in. */ + void **apData; /**< The actual data storage. */ + void *pPushBuf; /**< The push buffer. */ + +}; + +#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 @@ +#include +#include "sbuffer.h" + +SBuffer::SBuffer() : + nPos( 0 ), + bOpen( true ) +{ +} + +SBuffer::~SBuffer() +{ +} + +void SBuffer::close() +{ + bOpen = false; + fbData.clearData(); +} + +size_t SBuffer::read( char *pBuf, size_t nBytes ) +{ + size_t nLeft = fbData.getLength() - nPos; + if( nBytes > nLeft ) + nBytes = nLeft; + + if( nLeft == 0 ) + return 0; + + memcpy( pBuf, fbData.getData()+nPos, nBytes ); + nPos += nBytes; + + return nBytes; +} + +size_t SBuffer::write( const char *pBuf, size_t nBytes ) +{ + fbData.appendData( pBuf, nBytes ); + nPos += nBytes; + + return nBytes; +} + +long SBuffer::tell() +{ + return nPos; +} + +void SBuffer::seek( long offset ) +{ + nPos += offset; +} + +void SBuffer::setPos( long pos ) +{ + nPos = pos; +} + +void SBuffer::setPosEnd( long pos ) +{ + nPos = fbData.getLength() - pos; +} + +bool SBuffer::isEOS() +{ + return nPos == fbData.getLength(); +} + 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 @@ +#ifndef S_BUFFER_H +#define S_BUFFER_H + +#include + +#include "stream.h" +#include "flexbuf.h" + +class SBuffer : public Stream +{ +public: + SBuffer(); + virtual ~SBuffer(); + + virtual void close(); + virtual size_t read( char *pBuf, size_t nBytes ); + + /** + *@todo Update this to write at nPos, not just append data. + */ + virtual size_t write( const char *pBuf, size_t nBytes ); + + virtual long tell(); + virtual void seek( long offset ); + virtual void setPos( long pos ); + virtual void setPosEnd( long pos ); + virtual bool isEOS(); + + FlexBuf &getBuffer() + { + return fbData; + } + +private: + long nPos; + bool bOpen; + FlexBuf fbData; +}; + +#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 @@ +#include "serializable.h" + +Serializable::Serializable() +{ +} +Serializable::~Serializable() +{ +} 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 @@ +#ifndef SERIALIZER_H +#define SERIALIZER_H + +//#include "serializer.h" + +/** + * The base class for any class you want to serialize. Simply include this as + * a base class, implement the purely virtual serialize function and you've got + * an easily serializable class. + */ +class Serializable +{ +public: + /** + * Does nothing, here for completeness. + */ + Serializable(); + + /** + * Here to ensure the deconstructor is virtual. + */ + virtual ~Serializable(); + + /** + * This is the main workhorse of the serialization system, just override and + * you've got a serializable class. A reference to the Serializer archive + * used is passed in as your only parameter, query it to discover if you are + * loading or saving. + * @param ar A reference to the Serializer object to use. + */ + virtual void serialize( class Serializer &ar )=0; +}; + +#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 @@ +#include "serializer.h" +#include "serializable.h" +#include + +Serializer::Serializer(bool bLoading): + bLoading(bLoading) +{ +} +Serializer::~Serializer() +{ +} + +bool Serializer::isLoading() +{ + return bLoading; +} +Serializer &Serializer::operator<<(bool p) +{ + write( &p, sizeof(p) ); + return *this; +} +Serializer &Serializer::operator<<(int8_t p) +{ + write( &p, sizeof(p) ); + return *this; +} +Serializer &Serializer::operator<<(int16_t p) +{ + write( &p, sizeof(p) ); + return *this; +} +Serializer &Serializer::operator<<(int32_t p) +{ + write( &p, sizeof(p) ); + return *this; +} +Serializer &Serializer::operator<<(int64_t p) +{ + write( &p, sizeof(p) ); + return *this; +} +Serializer &Serializer::operator<<(uint8_t p) +{ + write( &p, sizeof(p) ); + return *this; +} +Serializer &Serializer::operator<<(uint16_t p) +{ + write( &p, sizeof(p) ); + return *this; +} +Serializer &Serializer::operator<<(uint32_t p) +{ + write( &p, sizeof(p) ); + return *this; +} +Serializer &Serializer::operator<<(uint64_t p) +{ + write( &p, sizeof(p) ); + return *this; +} +Serializer &Serializer::operator<<(long p) +{ + write( &p, sizeof(p) ); + return *this; +} +Serializer &Serializer::operator<<(float p) +{ + write( &p, sizeof(p) ); + return *this; +} +Serializer &Serializer::operator<<(double p) +{ + write( &p, sizeof(p) ); + return *this; +} +Serializer &Serializer::operator<<(long double p) +{ + write( &p, sizeof(p) ); + return *this; +} + +Serializer &Serializer::operator>>(bool &p) +{ + read( &p, sizeof(p) ); + return *this; +} +Serializer &Serializer::operator>>(int8_t &p) +{ + read( &p, sizeof(p) ); + return *this; +} +Serializer &Serializer::operator>>(int16_t &p) +{ + read( &p, sizeof(p) ); + return *this; +} +Serializer &Serializer::operator>>(int32_t &p) +{ + read( &p, sizeof(p) ); + return *this; +} +Serializer &Serializer::operator>>(int64_t &p) +{ + read( &p, sizeof(p) ); + return *this; +} +Serializer &Serializer::operator>>(uint8_t &p) +{ + read( &p, sizeof(p) ); + return *this; +} +Serializer &Serializer::operator>>(uint16_t &p) +{ + read( &p, sizeof(p) ); + return *this; +} +Serializer &Serializer::operator>>(uint32_t &p) +{ + read( &p, sizeof(p) ); + return *this; +} +Serializer &Serializer::operator>>(uint64_t &p) +{ + read( &p, sizeof(p) ); + return *this; +} +Serializer &Serializer::operator>>(long &p) +{ + read( &p, sizeof(p) ); + return *this; +} +Serializer &Serializer::operator>>(float &p) +{ + read( &p, sizeof(p) ); + return *this; +} +Serializer &Serializer::operator>>(double &p) +{ + read( &p, sizeof(p) ); + return *this; +} +Serializer &Serializer::operator>>(long double &p) +{ + read( &p, sizeof(p) ); + return *this; +} + +Serializer &Serializer::operator&&(bool &p) +{ + if (bLoading) + { + return *this >> p; + } + else + { + return *this << p; + } +} + +Serializer &Serializer::operator&&(int8_t &p) +{ + if (bLoading) + { + return *this >> p; + } + else + { + return *this << p; + } +} + +Serializer &Serializer::operator&&(int16_t &p) +{ + if (bLoading) + { + return *this >> p; + } + else + { + return *this << p; + } +} + +Serializer &Serializer::operator&&(int32_t &p) +{ + if (bLoading) + { + return *this >> p; + } + else + { + return *this << p; + } +} + +Serializer &Serializer::operator&&(int64_t &p) +{ + if (bLoading) + { + return *this >> p; + } + else + { + return *this << p; + } +} + +Serializer &Serializer::operator&&(uint8_t &p) +{ + if (bLoading) + { + return *this >> p; + } + else + { + return *this << p; + } +} + +Serializer &Serializer::operator&&(uint16_t &p) +{ + if (bLoading) + { + return *this >> p; + } + else + { + return *this << p; + } +} + +Serializer &Serializer::operator&&(uint32_t &p) +{ + if (bLoading) + { + return *this >> p; + } + else + { + return *this << p; + } +} + +Serializer &Serializer::operator&&(uint64_t &p) +{ + if (bLoading) + { + return *this >> p; + } + else + { + return *this << p; + } +} + +Serializer &Serializer::operator&&(float &p) +{ + if (bLoading) + { + return *this >> p; + } + else + { + return *this << p; + } +} + +Serializer &Serializer::operator&&(double &p) +{ + if (bLoading) + { + return *this >> p; + } + else + { + return *this << p; + } +} + +Serializer &Serializer::operator&&(long double &p) +{ + if (bLoading) + { + return *this >> p; + } + else + { + return *this << p; + } +} + + +Serializer &operator<<(Serializer &s, Serializable &p) +{ + p.serialize( s ); + return s; +} + +Serializer &operator>>(Serializer &s, Serializable &p) +{ + p.serialize( s ); + return s; +} + +Serializer &operator&&(Serializer &s, Serializable &p) +{ + if (s.isLoading()) + { + return s >> p; + } + else + { + return s << p; + } +} + +Serializer &operator<<( Serializer &ar, std::string &s ) +{ + ar << (uint32_t)s.length(); + ar.write( s.c_str(), s.length() ); + + return ar; +} + +Serializer &operator>>( Serializer &ar, std::string &s ) +{ + uint32_t l; + ar >> l; + char *tmp = new char[l+1]; + tmp[l] = '\0'; + ar.read( tmp, l ); + s = tmp; + delete[] tmp; + + return ar; +} + 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 @@ +#ifndef SERIALIZABLE_H +#define SERIALIZABLE_H + +#include +#include +#include +//#include "serializable.h" + +class Serializer +{ +private: + bool bLoading; +public: + bool isLoading(); + + enum + { + load = true, + save = false + }; + + Serializer(bool bLoading); + virtual ~Serializer(); + virtual void close()=0; + + virtual void write(const void *, int32_t)=0; + virtual void read(void *, int32_t)=0; + + virtual Serializer &operator<<(bool); + virtual Serializer &operator<<(int8_t); + virtual Serializer &operator<<(int16_t); + virtual Serializer &operator<<(int32_t); + virtual Serializer &operator<<(int64_t); + virtual Serializer &operator<<(uint8_t); + virtual Serializer &operator<<(uint16_t); + virtual Serializer &operator<<(uint32_t); + virtual Serializer &operator<<(uint64_t); + virtual Serializer &operator<<(long); + virtual Serializer &operator<<(float); + virtual Serializer &operator<<(double); + virtual Serializer &operator<<(long double); + + virtual Serializer &operator>>(bool &); + virtual Serializer &operator>>(int8_t &); + virtual Serializer &operator>>(int16_t &); + virtual Serializer &operator>>(int32_t &); + virtual Serializer &operator>>(int64_t &); + virtual Serializer &operator>>(uint8_t &); + virtual Serializer &operator>>(uint16_t &); + virtual Serializer &operator>>(uint32_t &); + virtual Serializer &operator>>(uint64_t &); + virtual Serializer &operator>>(long &); + virtual Serializer &operator>>(float &); + virtual Serializer &operator>>(double &); + virtual Serializer &operator>>(long double &); + + virtual Serializer &operator&&(bool &); + virtual Serializer &operator&&(int8_t &); + virtual Serializer &operator&&(int16_t &); + virtual Serializer &operator&&(int32_t &); + virtual Serializer &operator&&(int64_t &); + virtual Serializer &operator&&(uint8_t &); + virtual Serializer &operator&&(uint16_t &); + virtual Serializer &operator&&(uint32_t &); + virtual Serializer &operator&&(uint64_t &); + virtual Serializer &operator&&(float &); + virtual Serializer &operator&&(double &); + virtual Serializer &operator&&(long double &); + + //virtual Serializer &operator&(Serializable &); +}; + +Serializer &operator<<(Serializer &, class Serializable &); +Serializer &operator>>(Serializer &, class Serializable &); +Serializer &operator&&(Serializer &s, class Serializable &p); + +Serializer &operator<<(Serializer &, std::string &); +Serializer &operator>>(Serializer &, std::string &); + +#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 @@ +#include "serializerbinary.h" +#include "serializable.h" +#include "exceptions.h" + +SerializerBinary::SerializerBinary(FILE *fhFile, bool bLoading): + Serializer(bLoading), + fhFile(fhFile), + bCloseFile(false) +{ +} + +SerializerBinary::SerializerBinary(const char *sFileName, bool bLoading): + Serializer(bLoading), + bCloseFile(true) +{ + if (bLoading) + { + fhFile = fopen(sFileName, "rb"); + if( fhFile == NULL ) + throw FileException("Unable to open file: %s", sFileName ); + } + else + { + fhFile = fopen(sFileName, "wb"); + if( fhFile == NULL ) + throw FileException("Unable to open file: %s", sFileName ); + } +} + +SerializerBinary::~SerializerBinary() +{ + close(); +} + +void SerializerBinary::close() +{ + if (fhFile != NULL && bCloseFile ) + { + fclose(fhFile); + fhFile = NULL; + } +} + +void SerializerBinary::write(const void * pData, int32_t nSize) +{ + if( nSize == 0 ) + return; + + fwrite(pData, nSize, 1, fhFile); +} + +void SerializerBinary::read(void * pData, int32_t nSize) +{ + if( nSize == 0 ) + return; + + uint32_t nRead = fread(pData, nSize, 1, fhFile); + if( nRead < 1 ) + { + throw FileException( excodeEOF, "End of file read"); + } +} + 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 @@ +#ifndef SERIALIZER_BINARY_H +#define SERIALIZER_BINARY_H + +#include "serializer.h" +#include + +class SerializerBinary : public Serializer +{ +public: + SerializerBinary(FILE *fhFile, bool bLoading); + SerializerBinary(const char *sFileName, bool bLoading); + virtual ~SerializerBinary(); + + virtual void close(); + + virtual void write(const void *, int32_t); + virtual void read(void *, int32_t); + +private: + FILE *fhFile; + bool bCloseFile; +}; + +#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 @@ +#include "serializerbzip2.h" +#include "serializable.h" + +#include + +SerializerBZip2::SerializerBZip2(FILE *fhFile, bool bLoading): + Serializer(bLoading), + fhFile(fhFile), + bCloseFile(false) +{ + if( bLoading ) + { + bzFile = BZ2_bzReadOpen( &bzerror, fhFile, 0, 0, NULL, 0 ); + checkBZError(); + } + else + { + bzFile = BZ2_bzWriteOpen( &bzerror, fhFile, 9, 0, 0 ); + checkBZError(); + } +} + +SerializerBZip2::SerializerBZip2(char *sFileName, bool bLoading): + Serializer(bLoading), + bCloseFile(true) +{ + if (bLoading) + { + fhFile = fopen(sFileName, "rb"); + bzFile = BZ2_bzReadOpen( &bzerror, fhFile, 0, 0, NULL, 0 ); + checkBZError(); + } + else + { + fhFile = fopen(sFileName, "wb"); + bzFile = BZ2_bzWriteOpen( &bzerror, fhFile, 9, 0, 0 ); + checkBZError(); + } +} + +SerializerBZip2::~SerializerBZip2() +{ + close(); +} + +void SerializerBZip2::checkBZError() +{ +} + +void SerializerBZip2::close() +{ + if( bzFile != NULL ) + { + if( isLoading() ) + { + void *unused; + int nUnused; + BZ2_bzReadGetUnused( &bzerror, bzFile, &unused, &nUnused ); + BZ2_bzReadClose( &bzerror, bzFile ); + if( nUnused ) + fseek( fhFile, -nUnused, SEEK_CUR ); + } + else + { + BZ2_bzWriteClose( &bzerror, bzFile, 0, 0, 0 ); + } + checkBZError(); + bzFile = NULL; + } + if( fhFile != NULL && bCloseFile ) + { + fclose(fhFile); + fhFile = NULL; + } +} + +void SerializerBZip2::write(const void * pData, int32_t nSize) +{ + BZ2_bzWrite( &bzerror, bzFile, (void *)pData, nSize ); + checkBZError(); +} + +void SerializerBZip2::read(void * pData, int32_t nSize) +{ + BZ2_bzRead( &bzerror, bzFile, pData, nSize ); + checkBZError(); +} + 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 @@ +#ifndef SERIALIZER_BINARY_H +#define SERIALIZER_BINARY_H + +#include "serializer.h" +#include + +class SerializerBZip2 : public Serializer +{ +public: + SerializerBZip2(FILE *fhFile, bool bLoading); + SerializerBZip2(char *sFileName, bool bLoading); + virtual ~SerializerBZip2(); + + virtual void close(); + + virtual void write(const void *, int32_t); + virtual void read(void *, int32_t); + +private: + void checkBZError(); + FILE *fhFile; + void *bzFile; + bool bCloseFile; + int bzerror; +}; + +#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 @@ +#include "serializerconnection.h" + +SerializerConnection::SerializerConnection( + Connection *pCon, bool bIO, int nTimeSec, int nTimeUSec ) : + Serializer( bIO ), + pCon( pCon ), + nTimeSec( nTimeSec ), + nTimeUSec( nTimeUSec ) +{ +} + +SerializerConnection::~SerializerConnection() +{ +} + 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 @@ +#ifndef SERIALIZER_CONNECTION_H +#define SERIALIZER_CONNECTION_H + +#include + +#include "serializer.h" +#include "connection.h" + +/** + * + */ +class SerializerConnection : public Serializer +{ +public: + SerializerConnection( Connection *pCon, bool bIO, int nTimeSec, int nTimeUSec ); + virtual ~SerializerConnection(); + +private: + Connection *pCon; + int nTimeSec; + int nTimeUSec; +}; + +#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 @@ +#include "serializertext.h" + +SerializerText::SerializerText(FILE *fhFile, bool bLoading): + Serializer(bLoading), + fhFile(fhFile), + bCloseFile(false) +{ +} + +SerializerText::SerializerText(const char *sFileName, bool bLoading): + Serializer(bLoading), + bCloseFile(true) +{ + if (bLoading) + { + fhFile = fopen(sFileName, "rt"); + } + else + { + fhFile = fopen(sFileName, "wt"); + } +} + +SerializerText::~SerializerText() +{ + close(); +} + +void SerializerText::close() +{ + if (fhFile != NULL) + { + fclose(fhFile); + fhFile = NULL; + } +} + +void SerializerText::write(const void * pData, int32_t nSize) +{ + fwrite(pData, nSize, 1, fhFile); + fprintf(fhFile, "\n"); +} + +void SerializerText::read(void * pData, int32_t nSize) +{ + fread(pData, nSize, 1, fhFile); + fgetc(fhFile); +} + +Serializer &SerializerText::operator<<(bool p) +{ + fprintf(fhFile, "%hhd\n", p); + return *this; +} +Serializer &SerializerText::operator<<(int8_t p) +{ + fprintf(fhFile, "%hhd\n", p); + return *this; +} +Serializer &SerializerText::operator<<(int16_t p) +{ + fprintf(fhFile, "%hd\n", p); + return *this; +} +Serializer &SerializerText::operator<<(int32_t p) +{ + fprintf(fhFile, "%d\n", p); + return *this; +} +Serializer &SerializerText::operator<<(int64_t p) +{ + fprintf(fhFile, "%lld\n", p); + return *this; +} +Serializer &SerializerText::operator<<(uint8_t p) +{ + fprintf(fhFile, "%hhu\n", p); + return *this; +} +Serializer &SerializerText::operator<<(uint16_t p) +{ + fprintf(fhFile, "%hu\n", p); + return *this; +} +Serializer &SerializerText::operator<<(uint32_t p) +{ + fprintf(fhFile, "%u\n", p); + return *this; +} +Serializer &SerializerText::operator<<(uint64_t p) +{ + fprintf(fhFile, "%llu\n", p); + return *this; +} +Serializer &SerializerText::operator<<(float p) +{ + fprintf(fhFile, "%f\n", p); + return *this; +} +Serializer &SerializerText::operator<<(double p) +{ + fprintf(fhFile, "%f\n", p); + return *this; +} +Serializer &SerializerText::operator<<(long double p) +{ + fprintf(fhFile, "%Lf\n", p); + return *this; +} + +Serializer &SerializerText::operator>>(bool &p) +{ + fscanf(fhFile, "%hhd\n", ((signed char *)&p)); + return *this; +} +Serializer &SerializerText::operator>>(int8_t &p) +{ + fscanf(fhFile, "%hhd\n", &p); + return *this; +} +Serializer &SerializerText::operator>>(int16_t &p) +{ + fscanf(fhFile, "%hd\n", &p); + return *this; +} +Serializer &SerializerText::operator>>(int32_t &p) +{ + fscanf(fhFile, "%d\n", &p); + return *this; +} +Serializer &SerializerText::operator>>(int64_t &p) +{ + fscanf(fhFile, "%lld\n", &p); + return *this; +} +Serializer &SerializerText::operator>>(uint8_t &p) +{ + fscanf(fhFile, "%hhu\n", &p); + return *this; +} +Serializer &SerializerText::operator>>(uint16_t &p) +{ + fscanf(fhFile, "%hu\n", &p); + return *this; +} +Serializer &SerializerText::operator>>(uint32_t &p) +{ + fscanf(fhFile, "%u\n", &p); + return *this; +} +Serializer &SerializerText::operator>>(uint64_t &p) +{ + fscanf(fhFile, "%llu\n", &p); + return *this; +} +Serializer &SerializerText::operator>>(float &p) +{ + fscanf(fhFile, "%f\n", &p); + return *this; +} +Serializer &SerializerText::operator>>(double &p) +{ + fscanf(fhFile, "%lf\n", &p); + return *this; +} +Serializer &SerializerText::operator>>(long double &p) +{ + fscanf(fhFile, "%Lf\n", &p); + return *this; +} 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 @@ +#ifndef SERIALIZER_TEXT_H +#define SERIALIZER_TEXT_H + +#include "serializer.h" +#include + +class SerializerText : public Serializer +{ +public: + SerializerText(FILE *fhFile, bool bLoading); + SerializerText(const char *sFileName, bool bLoading); + virtual ~SerializerText(); + + virtual void close(); + + virtual void write(const void *, int32_t); + virtual void read(void *, int32_t); + + virtual Serializer &operator<<(bool); + virtual Serializer &operator<<(int8_t); + virtual Serializer &operator<<(int16_t); + virtual Serializer &operator<<(int32_t); + virtual Serializer &operator<<(int64_t); + virtual Serializer &operator<<(uint8_t); + virtual Serializer &operator<<(uint16_t); + virtual Serializer &operator<<(uint32_t); + virtual Serializer &operator<<(uint64_t); + virtual Serializer &operator<<(float); + virtual Serializer &operator<<(double); + virtual Serializer &operator<<(long double); + + virtual Serializer &operator>>(bool &); + virtual Serializer &operator>>(int8_t &); + virtual Serializer &operator>>(int16_t &); + virtual Serializer &operator>>(int32_t &); + virtual Serializer &operator>>(int64_t &); + virtual Serializer &operator>>(uint8_t &); + virtual Serializer &operator>>(uint16_t &); + virtual Serializer &operator>>(uint32_t &); + virtual Serializer &operator>>(uint64_t &); + virtual Serializer &operator>>(float &); + virtual Serializer &operator>>(double &); + virtual Serializer &operator>>(long double &); +private: + FILE *fhFile; + bool bCloseFile; +}; + +#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 @@ +#include "sfile.h" +#include "exceptions.h" + +SFile::SFile( const char *sName, const char *sFlags ) +{ + fh = fopen( sName, sFlags ); +} + +SFile::~SFile() +{ +} + +void SFile::close() +{ + if( fh ) + { + fclose( fh ); + fh = NULL; + } +} + +size_t SFile::read( char *pBuf, size_t nBytes ) +{ + if( !fh ) + throw FileException("File not open."); + + return fread( pBuf, 1, nBytes, fh ); +} + +size_t SFile::write( const char *pBuf, size_t nBytes ) +{ + if( !fh ) + throw FileException("File not open."); + + return fwrite( pBuf, 1, nBytes, fh ); +} + +long SFile::tell() +{ + if( !fh ) + throw FileException("File not open."); + + return ftell( fh ); +} + +void SFile::seek( long offset ) +{ + if( !fh ) + throw FileException("File not open."); + + fseek( fh, offset, SEEK_CUR ); +} + +void SFile::setPos( long pos ) +{ + if( !fh ) + throw FileException("File not open."); + + fseek( fh, pos, SEEK_SET ); +} + +void SFile::setPosEnd( long pos ) +{ + if( !fh ) + throw FileException("File not open."); + + fseek( fh, pos, SEEK_END ); +} + +bool SFile::isEOS() +{ + return feof( fh ); +} + 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 @@ +#ifndef SFILE_H +#define SFILE_H + +#include + +#include "stream.h" + +class SFile : public Stream +{ +public: + SFile( const char *sName, const char *sFlags ); + virtual ~SFile(); + + virtual void close(); + virtual size_t read( char *pBuf, size_t nBytes ); + virtual size_t write( const char *pBuf, size_t nBytes ); + + virtual long tell(); + virtual void seek( long offset ); + virtual void setPos( long pos ); + virtual void setPosEnd( long pos ); + virtual bool isEOS(); + +private: + FILE *fh; + +}; + +#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 @@ +#include +#include +#include + +#include "sha1.h" + +Sha1::Sha1() : + H0( 0x67452301 ), + H1( 0xefcdab89 ), + H2( 0x98badcfe ), + H3( 0x10325476 ), + H4( 0xc3d2e1f0 ), + unprocessedBytes( 0 ), + size( 0 ) +{ +} + +Sha1::~Sha1() +{ +} + +void Sha1::process() +{ + int t; + uint32_t a, b, c, d, e, K, f, W[80]; + + // starting values + a = H0; + b = H1; + c = H2; + d = H3; + e = H4; + + // copy and expand the message block + for( t = 0; t < 16; t++ ) W[t] = (bytes[t*4] << 24) + +(bytes[t*4 + 1] << 16) + +(bytes[t*4 + 2] << 8) + + bytes[t*4 + 3]; + for(; t< 80; t++ ) W[t] = lrot( W[t-3]^W[t-8]^W[t-14]^W[t-16], 1 ); + + /* main loop */ + uint32_t temp; + for( t = 0; t < 80; t++ ) + { + if( t < 20 ) { + K = 0x5a827999; + f = (b & c) | ((~b) & d); + } else if( t < 40 ) { + K = 0x6ed9eba1; + f = b ^ c ^ d; + } else if( t < 60 ) { + K = 0x8f1bbcdc; + f = (b & c) | (b & d) | (c & d); + } else { + K = 0xca62c1d6; + f = b ^ c ^ d; + } + temp = lrot(a,5) + f + e + W[t] + K; + e = d; + d = c; + c = lrot(b,30); + b = a; + a = temp; + //printf( "t=%d %08x %08x %08x %08x %08x\n",t,a,b,c,d,e ); + } + + /* add variables */ + H0 += a; + H1 += b; + H2 += c; + H3 += d; + H4 += e; + + //printf( "Current: %08x %08x %08x %08x %08x\n",H0,H1,H2,H3,H4 ); + /* all bytes have been processed */ + unprocessedBytes = 0; +} + +void Sha1::update( const char* data, int num ) +{ + // add these bytes to the running total + size += num; + + // repeat until all data is processed + while( num > 0 ) + { + // number of bytes required to complete block + int needed = 64 - unprocessedBytes; + + // number of bytes to copy (use smaller of two) + int toCopy = (num < needed) ? num : needed; + + // Copy the bytes + memcpy( bytes + unprocessedBytes, data, toCopy ); + + // Bytes have been copied + num -= toCopy; + data += toCopy; + unprocessedBytes += toCopy; + + // there is a full block + if( unprocessedBytes == 64 ) process(); + } +} + +unsigned char* Sha1::getDigest() +{ + // save the message size + uint32_t totalBitsL = size << 3; + uint32_t totalBitsH = size >> 29; + + // add 0x80 to the message + update( "\x80", 1 ); + + unsigned char footer[64] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + + // block has no room for 8-byte filesize, so finish it + if( unprocessedBytes > 56 ) + update( (char*)footer, 64 - unprocessedBytes); + + // how many zeros do we need + int neededZeros = 56 - unprocessedBytes; + + // store file size (in bits) in big-endian format + toBigEndian( totalBitsH, footer + neededZeros ); + toBigEndian( totalBitsL, footer + neededZeros + 4 ); + + // finish the final block + update( (char*)footer, neededZeros + 8 ); + + // allocate memory for the digest bytes + unsigned char* digest = new unsigned char[20]; + + // copy the digest bytes + toBigEndian( H0, digest ); + toBigEndian( H1, digest + 4 ); + toBigEndian( H2, digest + 8 ); + toBigEndian( H3, digest + 12 ); + toBigEndian( H4, digest + 16 ); + + // return the digest + return digest; +} + +uint32_t Sha1::lrot( uint32_t x, int bits ) +{ + return (x<>(32 - bits)); +}; + +void Sha1::toBigEndian( uint32_t num, unsigned char* byte ) +{ + byte[0] = (unsigned char)(num>>24); + byte[1] = (unsigned char)(num>>16); + byte[2] = (unsigned char)(num>>8); + byte[3] = (unsigned char)num; +} + 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 @@ +/* sha1.h + +Copyright (c) 2005 Michael D. Leonhard + +http://tamale.net/ + +This file is licensed under the terms described in the +accompanying LICENSE file. +*/ + +#ifndef SHA1_H +#define SHA1_H + +#include + +/** + * Calculates SHA-1 sums. This is based strongly on code from Michael D. + * Leonhard who released his code under the terms of the MIT license, thank you! + */ +class Sha1 +{ +public: + Sha1(); + ~Sha1(); + + void update( const char* data, int num ); + unsigned char* getDigest(); + + // utility methods + static uint32_t lrot( uint32_t x, int bits ); + static void toBigEndian( uint32_t in, unsigned char* out ); + +private: + // fields + uint32_t H0, H1, H2, H3, H4; + unsigned char bytes[64]; + int unprocessedBytes; + uint32_t size; + void process(); +}; + +#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 @@ +#ifndef SINGLETON_H +#define SINGLETON_H + +#include + +/** + * Provides singleton functionality in a modular sort of way. Make this the + * base class of any other class and you immediately gain singleton + * functionality. Be sure to make your constructor and various functions use + * intellegent scoping. Cleanup and instantiation are performed automatically + * for you at first use and program exit. There are two things that you must + * do when using this template, first is to inherit from it with the name of + * your class filling in for T and then make this class a friend of your class. + *@code + * // Making the Single Singleton: + * class Single : public Singleton + * { + * friend class Singleton; + * protected: + * Single(); + * ... + * }; + @endcode + * You can still add public functions and variables to your new Singleton child + * class, but your constructor should be protected (hence the need for the + * friend decleration). + *@author Mike Buland + */ +template +class Singleton +{ +protected: + /** + * Private constructor. This constructor is empty but has a body so that + * you can make your own override of it. Be sure that you're override is + * also protected. + */ + Singleton() {}; + +private: + /** + * Copy constructor, defined so that you could write your own as well. + */ + Singleton( const Singleton& ); + +public: + /** + * Get a handle to the contained instance of the contained class. It is + * a reference. + *@returns A reference to the contained object. + */ + static T &getInstance() + { + static T i; + return i; + } +}; + +#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 @@ +#ifndef SPTR_H +#define SPTR_H + +#include +#include + +template +class SPtr +{ +public: + SPtr() : + pRefCnt( NULL ), + pData( NULL ) + { + } + + ~SPtr() + { + decCount(); + } + + SPtr( const SPtr &src ) : + pRefCnt( src.pRefCnt ), + pData( src.pData ) + { + if( pRefCnt ) + (*pRefCnt) += 1; + } + + SPtr( T *pSrc ) : + pRefCnt( NULL ), + pData( pSrc ) + { + pRefCnt = new int32_t; + (*pRefCnt) = 1; + } + + int32_t count() + { + return *pRefCnt; + } + + T *operator->() const + { + return pData; + } + + T *operator*() const + { + return pData; + } + + SPtr operator=( const SPtr &src ) + { + decCount(); + pRefCnt = src.pRefCnt; + pData = src.pData; + (*pRefCnt) += 1; + + return *this; + } + + bool operator==( const SPtr &src ) + { + return pData == src.pData; + } + + operator bool() + { + return pRefCnt != NULL; + } + + bool isSet() + { + return pRefCnt != NULL; + } + +private: + void decCount() + { + if( pRefCnt ) + { + (*pRefCnt) -= 1; + //printf("Decrementing ref-count to %d\n", *pRefCnt ); + if( (*pRefCnt) == 0 ) + { + delete pRefCnt; + delete pData; + pRefCnt = NULL; + pData = NULL; + } + } + } + + int32_t *pRefCnt; + T *pData; +}; + +#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 @@ +#include "stack.h" + +void Stack::push( void *data ) +{ + lStackData.append( data ); +} + +void *Stack::top() +{ + return lStackData.getAt( lStackData.getSize()-1 ); +} + +void Stack::pop() +{ + lStackData.deleteAt( lStackData.getSize()-1 ); +} + +void *Stack::poptop() +{ + void *dat = top(); + pop(); + return dat; +} + +bool Stack::isEmpty() +{ + return lStackData.isEmpty(); +} + +void Stack::empty() +{ + lStackData.empty(); +} 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 @@ +#ifndef STACK_H +#define STACK_H +#include "linkedlist.h" + +/** An ultra-simple stack implementation that just uses a linked list. + *@author Mike Buland + */ +class Stack +{ +public: + /** Pushes a new value onto the top of the stack. + *@param data A new value for the stack. + *@author Mike Buland + */ + void push( void *data ); + + /** Returns the top value off of the stack, but doesn't remove it from the + * stack. + *@returns The value at the top of the stack. + *@author Mike Buland + */ + void *top(); + + /** Pops the top item off of the stack. + *@author Mike Buland + */ + void pop(); + + /** Gets the top item off of the stack, pops it off the stack, and returns + * it. + *@returns The value at the top of the stack. + *@author Mike Buland + */ + void *poptop(); + + /** Checks if the stack is empty. + *@returns True if the stack is empty, and false if it has things in it. + *@author Mike Buland + */ + bool isEmpty(); + + /** Empty the stack. + *@author Mike Buland + */ + void empty(); + +private: + LinkedList lStackData; /**< The actual stack data. */ +}; +#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 @@ +#include "staticstring.h" +#include "serializer.h" + +#include +#include +#include + +StaticString::StaticString() +{ + lpStr = NULL; + nLen = 0; +} + +StaticString::StaticString( int nLength ) +{ + lpStr = new char[nLength+1]; + nLen = nLength; + memset( lpStr, 0, nLength+1 ); +} + +StaticString::StaticString( const char *lpNewStr, int nNewLen ) +{ + lpStr = NULL; + nLen = 0; + setString( lpNewStr, nNewLen ); +} + +StaticString::StaticString( const char *lpNewStr ) +{ + lpStr = NULL; + nLen = 0; + setString( lpNewStr, -1 ); +} + +StaticString::StaticString( StaticString &xSrcStr, int nNewLen ) +{ + lpStr = NULL; + nLen = 0; + setString( xSrcStr, nNewLen ); +} + +StaticString::StaticString( StaticString &xSrcStr ) +{ + lpStr = NULL; + nLen = 0; + setString( xSrcStr, -1 ); +} + +StaticString::StaticString( const StaticString &xSrcStr ) +{ + nLen = xSrcStr.getLength(); + lpStr = new char[nLen]; + memcpy( lpStr, xSrcStr.getString(), nLen ); +} + +StaticString::~StaticString() +{ + if( lpStr != NULL ) delete[] lpStr; +} + +char *StaticString::getString() +{ + return lpStr; +} + +const char *StaticString::getString() const +{ + return lpStr; +} + +int StaticString::getLength() const +{ + return nLen; +} + +void StaticString::setLength( int nNewLength ) +{ + char *lpNewStr = new char[nNewLength+1]; + if( lpStr != NULL ) + { + strncpy( lpNewStr, lpStr, nNewLength ); + } + lpNewStr[nNewLength] = '\0'; + if( lpStr ) + { + delete[] lpStr; + } + lpStr = lpNewStr; + nLen = nNewLength; +} + +void StaticString::setString( const char *lpNewStr, int nNewLen ) +{ + if( lpStr ) + { + delete[] lpStr; + lpStr = NULL; + nLen = 0; + } + if( nNewLen < 0 ) + { + if( lpNewStr == NULL ) return; + nLen = strlen( lpNewStr ); + lpStr = new char[nLen+1]; + strcpy( lpStr, lpNewStr ); + } + else + { + nLen = nNewLen; + lpStr = new char[nLen+1]; + memset( lpStr, 0, nLen+1 ); + if( lpNewStr ) + strncpy( lpStr, lpNewStr, nNewLen ); + } +} + +void StaticString::setString( StaticString &sNewStr, int nNewLen ) +{ + if( lpStr ) + { + delete[] lpStr; + lpStr = NULL; + nLen = 0; + } + if( nNewLen < 0 ) + { + if( sNewStr.lpStr == NULL ) return; + nLen = sNewStr.nLen; + lpStr = new char[nLen+1]; + strcpy( lpStr, sNewStr.lpStr ); + } + else + { + nLen = nNewLen; + lpStr = new char[nLen+1]; + memset( lpStr, 0, nLen+1 ); + if( sNewStr.lpStr ) + strncpy( lpStr, sNewStr.lpStr, nNewLen ); + } +} + +StaticString &StaticString::operator=( StaticString &lpOtherStr ) +{ + setString( lpOtherStr ); + + return *this; +} + +StaticString &StaticString::operator=( std::string &lpOtherStr ) +{ + setString( lpOtherStr.c_str() ); + + return *this; +} + +StaticString &StaticString::operator=( const char *lpNewStr ) +{ + setString( lpNewStr ); + + return *this; +} + +StaticString::operator const char *() +{ + return lpStr; +} + +char StaticString::getAt( unsigned int nIndex ) +{ + if( nIndex < 0 || nIndex >= nLen ) + return '\0'; + + return lpStr[nIndex]; +} + +void StaticString::setAt( unsigned int nIndex, char cVal ) +{ + if( nIndex < 0 || nIndex >= nLen ) + return; + + lpStr[nIndex] = cVal; +} + +char &StaticString::operator[]( unsigned int nIndex ) +{ + if( nIndex < 0 || nIndex >= nLen ) + return lpStr[0]; + + return lpStr[nIndex]; +} + +StaticString::operator int() +{ + return nLen; +} + +char *StaticString::operator+( int nAmnt ) +{ + return lpStr + nAmnt; +} + +char *StaticString::operator-( int nAmnt ) +{ + return lpStr - nAmnt; +} + +void StaticString::clear() +{ + memset( lpStr, 0, nLen+1 ); +} + +void StaticString::serialize( Serializer &ar ) +{ + if( ar.isLoading() ) + { + ar >> nLen; + setLength( nLen ); + ar.read( lpStr, nLen ); + } + else + { + ar << nLen; + ar.write( lpStr, nLen ); + } +} + +bool StaticString::operator==( const char *str ) +{ + const char *a = str, *b = lpStr; + for(; *a == *b; a++, b++ ) if( *a == '\0' && *b == '\0' ) return true; + return false; +} + +bool StaticString::operator==( StaticString &str ) +{ + const char *a = str.lpStr, *b = lpStr; + for(; *a == *b; a++, b++ ) if( *a == '\0' && *b == '\0' ) return true; + return false; +} + +bool StaticString::operator!=( const char *str ) +{ + const char *a = str, *b = lpStr; + for(; *a == *b; a++, b++ ) if( *a == '\0' && *b == '\0' ) return false; + return true; +} + +bool StaticString::operator!=( StaticString &str ) +{ + const char *a = str.lpStr, *b = lpStr; + for(; *a == *b; a++, b++ ) if( *a == '\0' && *b == '\0' ) return false; + return true; +} +/* +unsigned long int StaticString::getHashCode() +{ + unsigned long int nPos = nLen; + unsigned long int j = 0; + for( const char *s = (const char *)lpStr; j< nLen; s++, j++ ) + { + nPos = *s + (nPos << 6) + (nPos << 16) - nPos; + } + return nPos; +} + +bool StaticString::compareForHash( Hashable &other ) +{ + if( ((StaticString &)other).nLen != nLen ) + return false; + + const char *a = ((StaticString &)other).lpStr; + const char *b = lpStr; + if( a == b ) + return true; + + for( unsigned long j = 0; j < nLen; j++, a++, b++ ) + if( *a != *b ) + return false; + + return true; +} +*/ 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 @@ +#ifndef STATIC_STRING_H +#define STATIC_STRING_H + +#include +#include "serializable.h" +//#include "hashable.h" + +/** + * Simple string managing class. Allows for dynamically allocated string data + * along with some minor caching to speed things up when accessing your + * string data. Really designed for making copies of strings easy and safe, + * and making accessing meta-info like length fast and reliable as well. + *@author Mike Buland + */ +class StaticString : public Serializable/*, public Hashable*/ +{ +public: + StaticString(); + StaticString( const char *lpNewStr, int nNewLen ); + StaticString( const char *lpNewStr ); + StaticString( StaticString &xSrcStr, int nNewLen ); + StaticString( StaticString &xSrcStr ); + StaticString( const StaticString &xSrcStr ); + StaticString( int nLength ); + virtual ~StaticString(); + + char *getString(); + const char *getString() const; + int getLength() const; + void setLength( int nNewLength ); + + void setString( const char *lpNewStr, int nNewLen=-1 ); + void setString( StaticString &sNewStr, int nNewLen=-1 ); + + char getAt( unsigned int nIndex ); + void setAt( unsigned int nIndex, char cVal ); + + class StaticString &operator=( class StaticString &lpOtherStr ); + class StaticString &operator=( std::string &lpOtherStr ); + class StaticString &operator=( const char *lpNewStr ); + operator const char *(); + char &operator[]( unsigned int nIndex ); + operator int(); + char *operator+( int nAmnt ); + char *operator-( int nAmnt ); + bool operator==( const char *str ); + bool operator==( StaticString &str ); + bool operator!=( const char *str ); + bool operator!=( StaticString &str ); + + void clear(); + + virtual void serialize( class Serializer &ar ); + + //virtual unsigned long int getHashCode(); + //virtual bool compareForHash( Hashable &other ); + +private: + char *lpStr; + uint32_t nLen; +}; + +#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 @@ +#include "stream.h" + +Stream::Stream() +{ +} + +Stream::~Stream() +{ +} + 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 @@ +#ifndef STREAM_H +#define STREAM_H + +#include +#include + +class Stream +{ +public: + Stream(); + virtual ~Stream(); + + virtual void close() = 0; + virtual size_t read( char *pBuf, size_t nBytes ) = 0; + virtual size_t write( const char *pBuf, size_t nBytes ) = 0; + + virtual long tell() = 0; + virtual void seek( long offset ) = 0; + virtual void setPos( long pos ) = 0; + virtual void setPosEnd( long pos ) = 0; + virtual bool isEOS() = 0; + +private: + +}; + +#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 @@ +#include "stringrep.h" + +int32_t stringlen( const char *s ) +{ + for( int32_t i = 0;; i++ ) + if( !s[i] ) + return i; +} + +char *stringdup( const char *s ) +{ + int len = stringlen( s ); + char *r = new char[len+1]; + for( int j = 0; j <= len; j++ ) + r[j] = s[j]; + + return r; +} + 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 @@ +#ifndef STRING_REP_H +#define STRING_REP_H + +#include + +/** + * Calculates the length of a string. + */ +int32_t stringlen( const char *s ); + +/** + * Identicle to strdup, which isn't available everywhere, but uses c++ memory + * facilities. Remember to use delete[] when freeing the returned string. + */ +char *stringdup( const char *s ); + +#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 @@ +#include "connection.h" + +int main() +{ + Connection c; + + c.open("localhost", 4001 ); + + c.appendOutput("w"); + c.writeOutput(); + + c.waitForInput( 6, 5, 0 ); + + printf("read: %s\n", c.getInput() ); + + c.close(); + + return 0; +} + 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 @@ +#include "confpair.h" +#include + +using namespace std; + +int main() +{ + ConfPair p1("DebugMode"); + p1.value() = 12; + cout << p1.value() << "\n"; + p1.value() = 55; + cout << p1.value() << "\n"; + + ConfPairBase &p = p1; + + p = "33.12"; + cout << p.getAsString(); +} + 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 @@ +#include +#include +#include +#include +#include "connection.h" + +int main() +{ + Connection c; + c.open("127.0.0.1", 12457 ); + + { + int newSocket = c.getSocket(); + int flags; + + flags = fcntl(newSocket, F_GETFL, 0); + flags |= O_NONBLOCK; + if (fcntl(newSocket, F_SETFL, flags) < 0) + { + return false; + } + } + + for( int i = 0; i < 50; i++ ) + { + usleep( 100000 ); + int nbytes = c.readInput(); + if( nbytes == 0 ) + printf("0 bytes, EOF?\n"); + else + printf("Got %d bytes, whacky...\n", nbytes ); + } + + c.close(); + + return 0; +} + 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 @@ +#include +#include "exceptions.h" + +int main() +{ + try + { + throw ExceptionBase( 42, "There was an error on line: %d", __LINE__ ); + } + catch( ExceptionBase &e ) + { + std::cout << "Error "<< e.getErrorCode() << ": " << e.what() << "\n"; + } + + throw ExceptionBase( 112, "This exception wasn't caught!"); +} 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 @@ +#include "formula.h" + +int main( int argc, char *argv[] ) +{ + if( argc < 2 ) return 0; + + Formula f; + double dOut = f.run( argv[1] ); + printf("%s = %f\n", argv[1], dOut ); + + return 0; +} + 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 @@ +#include "hash.h" +#include "fstring.h" + +FString genThing() +{ + FString bob; + bob.append("ab "); + bob += "cd "; + bob += "efg"; + + printf("---bob------\n%08X: %s\n", (unsigned int)bob.c_str(), bob.c_str() ); + return bob; +} + +void thing( FString str ) +{ + printf("Hey: %s\n", str.c_str() ); +} + +#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() ); +int main( int argc, char *argv ) +{ + FString str("th"); + + str.prepend("Hello "); + str.append("ere."); + + FString str2( str ); + pem; + str += " What's up?"; + pem; + str2 += " How are you?"; + pem; + str = str2; + pem; + + str2 = genThing(); + pem; + + str = str2; + pem; + + thing( str2 ); + thing("test."); + + printf("%d == %d\n", __calcHashCode( str ), __calcHashCode( str.c_str() ) ); +} + 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 @@ +#include "hash.h" +#include "staticstring.h" + +int main() +{ + const char *names[]={ + "Homer the Great", + "And Maggie Makes Three", + "Bart's Comet", + "Homie The Clown", + "Bart Vs Australia", + "Homer vs Patty and Selma", + "A star is burns", + "Lisa's Wedding", + "Two Dozen and One Greyhounds", + "The PTA Disbands", + "Round Springfield", + "The Springfield connection", + "Lemon of Troy", + "Who Shot Mr. Burns (Pt. 1)", + "Who Shot Mr. Burns (pt. 2)", + "Radioactive Man", + "Home Sweet Homediddly-dum-doodly", + "Bart Sells His Soul", + "Lisa the Vegetarian", + "Treehouse of horror VI", + "King Size Homer", + "Mother Simpson", + "Sideshow Bob's Last Gleaming", + "The Simpson's 138th Show Spectacular", + "Marge Be Not Proud", + "Team Homer", + "Two Bad Neighbors", + "Scenes From the Class Struggle in Springfield", + "Bart the Fink", + "Lisa the Iconoclast", + "Homer the Smithers", + "The Day the Violence Died", + "A Fish Called Selma", + "Bart on the road", + "22 Short Films about Springfield", + "The Curse of the Flying Hellfish", + "Much Apu about Nothing", + "Homerpalooza", + "The Summer of 4 Ft 2", + "Treehouse of Horror VII", + "You Only Move Twice", + "The Homer They Fall", + "Burns Baby Burns", + "Bart After Dark", + "A Millhouse Divided", + "Lisas Date With Destiny", + "Hurricane Neddy", + "The Mysterious Voyage of Our Homer", + "The Springfield Files", + "The Twisted World of Marge Simpson", + "Mountain of Madness", + NULL + }; + + Hash sTest; + + printf("Inserting\n-------------------\n\n"); + for( int j = 0; j < 33; j++ ) + { + sTest[names[j]] = j; + } + + printf("Test1: %d, Test2: %d\n", sTest.has("Lemon of Troy"), sTest.has(std::string("Lemon of Troy").c_str() ) ); + + sTest.has(std::string("Lemon of Troy").c_str() ); + + printf("Getting\n-------------------\n\n"); + + sTest.erase("Homer the Great"); + sTest["Bart's Comet"].erase(); + + for( Hash::iterator i = sTest.begin(); + i != sTest.end(); i++ ) + { + Hash::iterator j = i; + printf("%d: %s\n", (*j).second, (*j).first ); + } + + printf("Testing\n-------------------\n\n"); + for( int j = 0; j < 33; j++ ) + { + if( sTest.has(names[j]) ) + { + if( sTest[names[j]] != j ) + { + printf("'%s' should be %d, is %d\n", + names[j], j, + sTest[names[j]].value() + ); + } + } + else + { + printf("Missing element %d, '%s'\n", j, names[j] ); + } + } + + printf("Clearing\n-------------------\n\n"); + + sTest.clear(); + + for( Hash::iterator i = sTest.begin(); + i != sTest.end(); i++ ) + { + Hash::iterator j = i; + printf("%d: %s\n", (*j).second, (*j).first ); + } + +} + 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 @@ +#include +#include +#include "hashtable.h" +#include "hashfunctioncasestring.h" + +int main() +{ + const char *names[]={ + "Homer the Great", + "And Maggie Makes Three", + "Bart's Comet", + "Homie The Clown", + "Bart Vs Australia", + "Homer vs Patty and Selma", + "A star is burns", + "Lisa's Wedding", + "Two Dozen and One Greyhounds", + "The PTA Disbands", + "Round Springfield", + "The Springfield connection", + "Lemon of Troy", + "Who Shot Mr. Burns (Pt. 1)", + "Who Shot Mr. Burns (pt. 2)", + "Radioactive Man", + "Home Sweet Homediddly-dum-doodly", + "Bart Sells His Soul", + "Lisa the Vegetarian", + "Treehouse of horror VI", + "King Size Homer", + "Mother Simpson", + "Sideshow Bob's Last Gleaming", + "The Simpson's 138th Show Spectacular", + "Marge Be Not Proud", + "Team Homer", + "Two Bad Neighbors", + "Scenes From the Class Struggle in Springfield", + "Bart the Fink", + "Lisa the Iconoclast", + "Homer the Smithers", + "The Day the Violence Died", + "A Fish Called Selma", + "Bart on the road", + "22 Short Films about Springfield", + "The Curse of the Flying Hellfish", + "Much Apu about Nothing", + "Homerpalooza", + "The Summer of 4 Ft 2", + "Treehouse of Horror VII", + "You Only Move Twice", + "The Homer They Fall", + "Burns Baby Burns", + "Bart After Dark", + "A Millhouse Divided", + "Lisas Date With Destiny", + "Hurricane Neddy", + "The Mysterious Voyage of Our Homer", + "The Springfield Files", + "The Twisted World of Marge Simpson", + "Mountain of Madness", + NULL + }; + + HashTable h( new HashFunctionCaseString(), 5, false ); + + int j; + printf("Inserting...\n"); + for( j = 0; j < 10; j++ ) + { + h.insert( names[j], (void *)(j+1) ); + h.insert( names[j], (void *)(j+1) ); + printf("Capacity: %lu, Size: %lu, Load: %f\n", + h.getCapacity(), + h.getSize(), + h.getLoad() + ); + } + + for( j = 0; j < 10; j++ ) + { + printf("\"%s\" = %d\n", names[j], (int)h[names[j]] ); + } + + printf("\nDeleting some...\n"); + + for( int k = 0; k < 7; k++ ) + { + h.del( names[k] ); + //h.insert( names[j], (void *)(j+1) ); + printf("Capacity: %lu, Size: %lu, Load: %f\n", + h.getCapacity(), + h.getSize(), + h.getLoad() + ); + } + + printf("\nInserting more...\n"); + + for( ; names[j] != NULL; j++ ) + { + h.insert( names[j], (void *)(j+1) ); + printf("Capacity: %lu, Size: %lu, Load: %f\n", + h.getCapacity(), + h.getSize(), + h.getLoad() + ); + } +} 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 @@ +#include "hash.h" +#include + +int main() +{ + char *a, *b; + a = new char[10]; + b = new char[10]; + strcpy( a, "Hey there"); + strcpy( b, "Hey there"); + printf("Same: %s\n", __cmpHashKeys( a, b )?"yes":"no"); + + return 0; +} + 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 @@ +#include "httpconnectionmonitor.h" +#include "http.h" +#include "exceptions.h" +#include + +HttpConnectionMonitor::HttpConnectionMonitor() +{ +} + +HttpConnectionMonitor::~HttpConnectionMonitor() +{ +} + +bool HttpConnectionMonitor::onNewConnection( Connection *pCon, int nPort ) +{ + printf("Got connection on port %d\n", nPort ); + + try + { + pCon->readInput( 60, 0 ); + printf("#######################\n%s\n#######################\n", pCon->getInput() ); + + Http hp( pCon ); + while( hp.parseRequest() == false ); + printf("Done parsing.\n\n"); + + if( hp.getRequestType() == Http::reqGet ) + { + printf("\"\"\"%s\"\"\"\n", hp.getRequestURI() ); + if( !strcmp( hp.getRequestURI(), "/" ) ) + { + std::string content("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>"); + hp.buildResponse(); + hp.setResponseContent( + "text/html", + content.c_str(), + content.size() + ); + hp.sendResponse(); + } + else + { + 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>"); + hp.buildResponse( 404, "File not found."); + hp.setResponseContent( + "text/html", + content.c_str(), + content.size() + ); + hp.sendResponse(); + } + } + else + { + printf("Non get: %s\n", hp.getRequestTypeStr() ); + pCon->appendOutput("HTTP/1.1 100 Continue\r\n\r\n"); + } + pCon->writeOutput(); + //for( int j = 0; j < 50; j++ ) + { + pCon->readInput( 1, 0 ); + //printf("Size so far: %d\n", pCon->getInputAmnt() ); + } + + if( pCon->hasInput() ) + { + std::string s( pCon->getInput(), pCon->getInputAmnt() ); + + pCon->printInputDebug(); + //printf("Reamining data\n==============\n%s\n==============\n", + // s.c_str() ); + } + + pCon->disconnect(); + } + catch( ConnectionException &e ) + { + printf("Connection: %s\n", e.what() ); + } + + return true; +} + +bool HttpConnectionMonitor::onClosedConnection( Connection *pCon ) +{ + return true; +} + 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 @@ +#ifndef HTTPCONNECTIONMONITOR_H +#define HTTPCONNECTIONMONITOR_H + +#include "connectionmonitor.h" + +class HttpConnectionMonitor : public ConnectionMonitor +{ +public: + HttpConnectionMonitor(); + ~HttpConnectionMonitor(); + + bool onNewConnection( Connection *pCon, int nPort ); + bool onClosedConnection( Connection *pCon ); +}; + +#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 @@ +#include "connectionmanager.h" +#include "httpconnectionmonitor.h" + +int main() +{ + printf("Starting server...\n"); + + ConnectionManager srv; + HttpConnectionMonitor http; + + srv.setConnectionMonitor( &http ); + + printf("Listening on port 7331\n"); + srv.startServer( 7331 ); + + for(;;) + { + srv.scanConnections( 5000, false ); + } + + return 0; +} 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 @@ +#include <stdio.h> +#include <stdlib.h> +#include <iostream> +#include "multilog.h" +#include "multilogtext.h" + +class Test +{ +public: + Test() + { + MultiLineLog( 4, "Test init'd\n"); + } +}; + +int main() +{ + MultiLog &xLog = MultiLog::getInstance(); + + xLog.LineLog( 2, "Hello again"); + + MultiLog::getInstance().addChannel( + new MultiLogText( STDOUT_FILENO, "%02y-%02m-%02d %02h:%02M:%02s: %t" ) + ); + + MultiLineLog( MultiLog::LError, "Hi there!"); + Test t; +} + 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 @@ +#include <stdio.h> +#include <string.h> +#include "md5.h" + +int main() +{ + md5 mproc; + md5sum sum; + char hexstr[33]; + + memset( hexstr, 0, 33 ); + + mproc.sumString( &sum, "qwertyuiopasdfgh" ); + mproc.sumToHex( &sum, hexstr ); + printf("sum: %s\n", hexstr ); + printf("chk: 1ebfc043d8880b758b13ddc8aa1638ef\n"); + + return 0; +} 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 @@ +#include "ordhash.h" +#include <string> + +typedef struct eldef +{ + eldef( int a, int b, const std::string &c ) : + id( a ), nSequence( b ), sName( c ) {} + int id; + int nSequence; + std::string sName; +} eldef; + +struct seqcmp +{ + bool operator()( eldef **a, eldef **b ) + { + return (*a)->nSequence < (*b)->nSequence; + } +}; + +struct namcmp +{ + bool operator()( eldef **a, eldef **b ) + { + return (*a)->sName < (*b)->sName; + } +}; + +typedef OrdHash<int, eldef, seqcmp> AHash; +//typedef OrdHash<int, eldef, namcmp> AHash; + +int main() +{ + AHash hsh; + hsh[1] = eldef( 0, 43, "Bob"); + hsh[4] = eldef( 1, 443, "Abby"); + hsh[2] = eldef( 2, 1, "Name"); + hsh[5] = eldef( 3, 0, "Catagory"); + hsh[32] = eldef( 4, 12, "Epilogue"); + + for( AHash::iterator i = hsh.begin(); i != hsh.end(); i++ ) + { + eldef e = (*i).second; + printf("%d, %d, %s\n", e.id, e.nSequence, e.sName.c_str() ); + } + +} + 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 @@ +#include "param.h" +#include <stdio.h> + +Param::Param() +{ + addHelpBanner("param - A test of the libbu++ parameter systems\n" + "Enjoy with care and caution\n\nTest stuff:\n"); + addParam( "name", 's', mkproc( Param::printStuff ), &str, "Test a param param" ); + //addParam( "name", &str ); + addParam( "job", 'U', mkproc( Param::printStuff ), "Test a paramless param" ); + + addHelpBanner("\nInformational:\n"); + addParam( "help", mkproc( ParamProc::help ), "Help!" ); + + addHelpBanner("\nThanks for trying my test!\n\n"); +} + +Param::~Param() +{ +} + +int Param::printStuff( int argc, char *argv[] ) +{ + printf("------------%02d-------------\n", argc ); + for( int j = 0; j < argc; j++ ) + { + printf("%d: %s\n", j, argv[j] ); + } + printf("---------------------------\n" ); + printf("SETVAR===\"%s\"\n", str.c_str() ); + + return 1; +} + +int main( int argc, char *argv[] ) +{ + if( argc == 1 ) + { + printf("You have to enter some parameter, try '--help'\n\n"); + return 0; + } + + Param p; + p.process( argc, argv ); +} + 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 @@ +#ifndef PARAM_H +#define PARAM_H + +#include <stdint.h> + +#include "paramproc.h" + +class Param : public ParamProc +{ +public: + Param(); + virtual ~Param(); + +private: + int printStuff( int argc, char *argv[] ); + + std::string str; + uint32_t uint32; +}; + +#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 @@ +#include "plugger.h" +#include "plugin.h" + +int main() +{ + Plugger<Plugin> p; + + p.registerExternalPlugin( "./guy.so", "Guy" ); + + Plugin *t = p.instantiate( "Guy" ); + + p.destroy( t ); +} + 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 @@ +#include "plugin.h" + +Plugin::Plugin() +{ +} + +Plugin::~Plugin() +{ +} + 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 @@ +#ifndef PLUGIN_H +#define PLUGIN_H + +class Plugin +{ +public: + Plugin(); + virtual ~Plugin(); + +private: + +}; + +#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 @@ +#define _QSORT_SWAP(a, b, t) ((void)((t = *a), (*a = *b), (*b = t))) + +/* Discontinue quicksort algorithm when partition gets below this size. + This particular magic number was chosen to work best on a Sun 4/260. */ +#define _QSORT_MAX_THRESH 4 + +/* Stack node declarations used to store unfulfilled partition obligations + * (inlined in QSORT). +typedef struct { + QSORT_TYPE *_lo, *_hi; +} qsort_stack_node; + */ + +/* The next 4 #defines implement a very fast in-line stack abstraction. */ +/* The stack needs log (total_elements) entries (we could even subtract + log(MAX_THRESH)). Since total_elements has type unsigned, we get as + upper bound for log (total_elements): + bits per byte (CHAR_BIT) * sizeof(unsigned). */ +#define _QSORT_STACK_SIZE (8 * sizeof(unsigned)) +#define _QSORT_PUSH(top, low, high) \ + (((top->_lo = (low)), (top->_hi = (high)), ++top)) +#define _QSORT_POP(low, high, top) \ + ((--top, (low = top->_lo), (high = top->_hi))) +#define _QSORT_STACK_NOT_EMPTY (_stack < _top) + + +/* Order size using quicksort. This implementation incorporates + four optimizations discussed in Sedgewick: + + 1. Non-recursive, using an explicit stack of pointer that store the + next array partition to sort. To save time, this maximum amount + of space required to store an array of SIZE_MAX is allocated on the + stack. Assuming a 32-bit (64 bit) integer for size_t, this needs + only 32 * sizeof(stack_node) == 256 bytes (for 64 bit: 1024 bytes). + Pretty cheap, actually. + + 2. Chose the pivot element using a median-of-three decision tree. + This reduces the probability of selecting a bad pivot value and + eliminates certain extraneous comparisons. + + 3. Only quicksorts TOTAL_ELEMS / MAX_THRESH partitions, leaving + insertion sort to order the MAX_THRESH items within each partition. + This is a big win, since insertion sort is faster for small, mostly + sorted array segments. + + 4. The larger of the two sub-partitions is always pushed onto the + stack first, with the algorithm then concentrating on the + smaller partition. This *guarantees* no more than log (total_elems) + stack size is needed (actually O(1) in this case)! */ + +/* The main code starts here... */ + +template<typename QSORT_TYPE, typename QSORT_LTT> +void qsrt( QSORT_TYPE *QSORT_BASE, int QSORT_NELT ) +{ + QSORT_LTT QSORT_LT; + QSORT_TYPE *const _base = (QSORT_BASE); + const unsigned _elems = (QSORT_NELT); + QSORT_TYPE _hold; + + /* Don't declare two variables of type QSORT_TYPE in a single + * statement: eg `TYPE a, b;', in case if TYPE is a pointer, + * expands to `type* a, b;' wich isn't what we want. + */ + + if (_elems > _QSORT_MAX_THRESH) { + QSORT_TYPE *_lo = _base; + QSORT_TYPE *_hi = _lo + _elems - 1; + struct { + QSORT_TYPE *_hi; QSORT_TYPE *_lo; + } _stack[_QSORT_STACK_SIZE], *_top = _stack + 1; + + while (_QSORT_STACK_NOT_EMPTY) { + QSORT_TYPE *_left_ptr; QSORT_TYPE *_right_ptr; + + /* Select median value from among LO, MID, and HI. Rearrange + LO and HI so the three values are sorted. This lowers the + probability of picking a pathological pivot value and + skips a comparison for both the LEFT_PTR and RIGHT_PTR in + the while loops. */ + + QSORT_TYPE *_mid = _lo + ((_hi - _lo) >> 1); + + if (QSORT_LT (_mid, _lo)) + _QSORT_SWAP (_mid, _lo, _hold); + if (QSORT_LT (_hi, _mid)) + _QSORT_SWAP (_mid, _hi, _hold); + else + goto _jump_over; + if (QSORT_LT (_mid, _lo)) + _QSORT_SWAP (_mid, _lo, _hold); + _jump_over:; + + _left_ptr = _lo + 1; + _right_ptr = _hi - 1; + + /* Here's the famous ``collapse the walls'' section of quicksort. + Gotta like those tight inner loops! They are the main reason + that this algorithm runs much faster than others. */ + do { + while (QSORT_LT (_left_ptr, _mid)) + ++_left_ptr; + + while (QSORT_LT (_mid, _right_ptr)) + --_right_ptr; + + if (_left_ptr < _right_ptr) { + _QSORT_SWAP (_left_ptr, _right_ptr, _hold); + if (_mid == _left_ptr) + _mid = _right_ptr; + else if (_mid == _right_ptr) + _mid = _left_ptr; + ++_left_ptr; + --_right_ptr; + } + else if (_left_ptr == _right_ptr) { + ++_left_ptr; + --_right_ptr; + break; + } + } while (_left_ptr <= _right_ptr); + + /* Set up pointers for next iteration. First determine whether + left and right partitions are below the threshold size. If so, + ignore one or both. Otherwise, push the larger partition's + bounds on the stack and continue sorting the smaller one. */ + + if (_right_ptr - _lo <= _QSORT_MAX_THRESH) { + if (_hi - _left_ptr <= _QSORT_MAX_THRESH) + /* Ignore both small partitions. */ + _QSORT_POP (_lo, _hi, _top); + else + /* Ignore small left partition. */ + _lo = _left_ptr; + } + else if (_hi - _left_ptr <= _QSORT_MAX_THRESH) + /* Ignore small right partition. */ + _hi = _right_ptr; + else if (_right_ptr - _lo > _hi - _left_ptr) { + /* Push larger left partition indices. */ + _QSORT_PUSH (_top, _lo, _right_ptr); + _lo = _left_ptr; + } + else { + /* Push larger right partition indices. */ + _QSORT_PUSH (_top, _left_ptr, _hi); + _hi = _right_ptr; + } + } + } + + /* Once the BASE array is partially sorted by quicksort the rest + is completely sorted using insertion sort, since this is efficient + for partitions below MAX_THRESH size. BASE points to the + beginning of the array to sort, and END_PTR points at the very + last element in the array (*not* one beyond it!). */ + + { + QSORT_TYPE *const _end_ptr = _base + _elems - 1; + QSORT_TYPE *_tmp_ptr = _base; + register QSORT_TYPE *_run_ptr; + QSORT_TYPE *_thresh; + + _thresh = _base + _QSORT_MAX_THRESH; + if (_thresh > _end_ptr) + _thresh = _end_ptr; + + /* Find smallest element in first threshold and place it at the + array's beginning. This is the smallest array element, + and the operation speeds up insertion sort's inner loop. */ + + for (_run_ptr = _tmp_ptr + 1; _run_ptr <= _thresh; ++_run_ptr) + if (QSORT_LT (_run_ptr, _tmp_ptr)) + _tmp_ptr = _run_ptr; + + if (_tmp_ptr != _base) + _QSORT_SWAP (_tmp_ptr, _base, _hold); + + /* Insertion sort, running from left-hand-side + * up to right-hand-side. */ + + _run_ptr = _base + 1; + while (++_run_ptr <= _end_ptr) { + _tmp_ptr = _run_ptr - 1; + while (QSORT_LT (_run_ptr, _tmp_ptr)) + --_tmp_ptr; + + ++_tmp_ptr; + if (_tmp_ptr != _run_ptr) { + QSORT_TYPE *_trav = _run_ptr + 1; + while (--_trav >= _run_ptr) { + QSORT_TYPE *_hi; QSORT_TYPE *_lo; + _hold = *_trav; + + for (_hi = _lo = _trav; --_lo >= _tmp_ptr; _hi = _lo) + *_hi = *_lo; + *_hi = _hold; + } + } + } + } + +} + + +struct cc +{ + bool operator()( int *a, int *b ) + { + return *a < *b; + } +}; + +#include <stdio.h> + +int main() +{ + int lst[] = { 43, 1, 342, 12, 491, 32, 12321, 32, 3, -3 }; + + for( int j = 0; j < 10; j++ ) + printf("%s%d", (j>0)?", ":"", lst[j] ); + printf("\n"); + qsrt<int, cc>( lst, 10 ); + for( int j = 0; j < 10; j++ ) + printf("%s%d", (j>0)?", ":"", lst[j] ); + printf("\n"); +} + 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 @@ +#include "sbuffer.h" + +int main() +{ + SBuffer buf; + + buf.write("abcdefg", 7 ); + + printf("tell: %ld\n", buf.tell() ); + + char abuf[6]; + int nRead; + nRead = buf.read( abuf, 5 ); + abuf[nRead] = '\0'; + printf("Read %d bytes \"%s\"\n", nRead, abuf ); + + buf.setPos( 0 ); + nRead = buf.read( abuf, 5 ); + abuf[nRead] = '\0'; + printf("Read %d bytes \"%s\"\n", nRead, abuf ); + + nRead = buf.read( abuf, 5 ); + abuf[nRead] = '\0'; + printf("Read %d bytes \"%s\"\n", nRead, abuf ); + +} + 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 @@ +#include "serializerbinary.h" +#include "staticstring.h" +#include <stdio.h> +#include <string> + +int main() +{ + int32_t one; + double two; + bool three; + StaticString s("Test string!"); + std::string ss("Another test string"); + SerializerBinary ar("hello.dat", false); + ar << (int)85; + ar << (double)2.63434; + ar << false; + ar << ss; + ar.close(); + + one = 0; two = 0; three = true; s = "die"; + + SerializerBinary ar2("hello.dat", true); + ar2 >> one; + ar2 >> two; + ar2 >> three; + ar2 >> s; + + printf("we got %d - %f - %s - \"%s\"\n", one, two, (three ? "true":"false"), s.getString() ); + return 0; +} 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 @@ +#include "serializertext.h" +#include "staticstring.h" +#include <iostream> + +int main() +{ + StaticString s("You're a dog!!"); + SerializerText ar("hello.dat", false); + + ar << 4 << 3.993 << true << s; + + ar.close(); + + int one=0;float two=0.0;bool three=false; s = ""; + + SerializerText ar2("hello.dat", true); + + ar2 >> one; + ar2 >> two; + ar2 >> three; + ar2 >> s; + + //printf("out: %d, %f, %s, \"%s\"\n", one, two, (three ? "true" : "false"), s.getString()); + std::cout << one << ", " << two << ", " << three << ", " << s.getString() << "\n"; + + return 0; +} + 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 @@ +#include "sha1.h" +#include "sfile.h" + +#define BS 1024 + +int main( int argc, char *argv[] ) +{ + argc--; argv++; + + if( argc == 0 ) + { + printf("Provide a filename.\n"); + return 0; + } + + char buf[BS]; + + Sha1 s; + SFile fin( *argv, "rb" ); + for(;;) + { + int nRead = fin.read( buf, BS ); + if( nRead == 0 ) + break; + + s.update( buf, nRead ); + if( nRead < BS ) + break; + } + + unsigned char *dig = s.getDigest(); + + char val[]={"0123456789ABCDEF"}; + + for( int j = 0; j < 20; j++ ) + { + putchar( val[dig[j]>>4] ); + putchar( val[dig[j]&0x0F] ); + } + putchar('\n'); + + delete[] dig; +} + 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 @@ +#include <stdio.h> +#include "sptr.h" + +class Annoy +{ +public: + Annoy() : nCnt( 0 ) + { + printf("Created.\n"); + } + + ~Annoy() + { + printf("Destroyed.\n"); + } + + void go() + { + printf("%d: I'm annoying.\n", ++nCnt); + } + + int nCnt; +}; + +void beAnnoying( SPtr<Annoy> bob ) +{ + printf("bob-Count: %d\n", bob.count() ); + bob->go(); +} + +int main() +{ + SPtr<Annoy> pt( new Annoy ); + printf("Count: %d\n", pt.count() ); + pt->go(); + + { + SPtr<Annoy> pt2 = pt; + printf("Count: %d\n", pt2.count() ); + + pt2->go(); + + { + SPtr<Annoy> pt3( pt2 ); + printf("Count: %d\n", pt3.count() ); + + pt3->go(); + + beAnnoying( pt3 ); + } + printf("Count: %d\n", pt.count() ); + } + printf("Count: %d\n", pt.count() ); +} + 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 @@ +#include "connectionmanager.h" +#include "programlink.h" +#include "linkedlist.h" +#include "protocol.h" + +class StressProtocol : public Protocol +{ +public: + bool onNewData() + { + switch( getConnection()->getInput()[0] ) + { + case 'd': + throw "Hello"; + break; + + case 'w': + getConnection()->appendOutput("Hello"); + break; + }; + + return true; + } + + bool onNewConnection() + { + return true; + } +}; + +class StressMonitor : public ConnectionMonitor, public ProgramLink +{ +public: + bool init() + { + return true; + } + + bool deInit() + { + return true; + } + + bool timeSlice() + { + return true; + } + + bool onNewConnection( Connection *pCon, int nPort ) + { + StressProtocol *sp = new StressProtocol(); + pCon->setProtocol( sp ); + + printf(" sys: New connection: socket(%d), port(%d)\n", + pCon->getSocket(), nPort ); + + return true; + } + + bool onClosedConnection( Connection *pCon ) + { + printf(" sys: Closed connection: socket(%d)\n", + pCon->getSocket() ); + + return true; + } + + LinkMessage *processIRM( LinkMessage *pMsg ) + { + return NULL; + } +}; + +int main() +{ + printf("Starting server...\n"); + + ConnectionManager srv; + StressMonitor telnet; + + srv.setConnectionMonitor( &telnet ); + + srv.startServer( 4001 ); + + for(;;) + { + srv.scanConnections( 5000, false ); + } + + return 0; +} 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 @@ +#include <stdio.h> +#include "hashfunctionstring.h" + +int main( int argc, char *argv[] ) +{ + HashFunctionString h; + + printf("\"%s\": %lu\n", argv[1], h.hash( argv[1] ) ); + + return 0; +} + 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 @@ +#include "connectionmanager.h" +#include "telnetmonitor.h" + +int main() +{ + printf("Starting server...\n"); + + ConnectionManager srv; + TelnetMonitor telnet; + + srv.setConnectionMonitor( &telnet ); + + srv.startServer( 4001 ); + + for(;;) + { + srv.scanConnections( 5000, false ); + } + + return 0; +} 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 @@ +#include "telnetmonitor.h" +#include "protocoltelnet.h" +#include <sys/stat.h> + +TelnetMonitor::TelnetMonitor() +{ +} + +TelnetMonitor::~TelnetMonitor() +{ +} + +bool TelnetMonitor::init() +{ + return true; +} + +bool TelnetMonitor::deInit() +{ + return true; +} + +bool TelnetMonitor::timeSlice() +{ + for( int j = 0; j < lCon.getSize(); j++ ) + { + if( ((Connection *)lCon[j])->hasInput() ) + { + printf("%s\n", ((Connection *)lCon[j])->getInput() ); + } + } + return true; +} + +LinkMessage* TelnetMonitor::processIRM( LinkMessage *pMsg ) +{ + return NULL; +} + +bool TelnetMonitor::onNewConnection( Connection *pCon, int nPort ) +{ + ProtocolTelnet *pt = new ProtocolTelnet(); + pCon->setProtocol( pt ); + + lCon.append( pt ); + + return true; +} + +bool TelnetMonitor::onClosedConnection( Connection *pCon ) +{ + return true; +} + 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 @@ +#ifndef HTTPCONNECTIONMONITOR_H +#define HTTPCONNECTIONMONITOR_H + +#include "connectionmonitor.h" +#include "programlink.h" +#include "linkedlist.h" + +class TelnetMonitor : public ConnectionMonitor, public ProgramLink +{ +public: + TelnetMonitor(); + ~TelnetMonitor(); + + bool init(); + bool deInit(); + bool timeSlice(); + LinkMessage* processIRM( LinkMessage *pMsgIn ); + + bool onNewConnection( Connection *pCon, int nPort ); + bool onClosedConnection( Connection *pCon ); + +private: + LinkedList lCon; +}; + +#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 @@ +#include "xmlfilereader.h" +#include "xmlstringreader.h" +#include "xmlfilewriter.h" + +int main( int argc, char *argv[] ) +{ + if( argc < 4 ) + { + printf("Usage: %s f <file in> <file out>\n", argv[0] ); + printf(" %s s <xml string> <file out>\n\n", argv[0] ); + return 0; + } + + if( argv[1][0] == 'f' ) + { + XmlFileReader r( argv[2], true ); +// XmlFileWriter w( argv[3], "\t", r.detatchRoot() ); +// w.write(); + } + else if( argv[1][0] == 's' ) + { + XmlStringReader r( argv[2], true ); + XmlFileWriter w(stdout, "\t", r.detatchRoot() ); + w.write(); + } + + return 0; +} + 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 @@ +#include "xmlwriter.h" + +int main() +{ + printf("Testing Xml Replacement...\n"); + XmlDocument w; + + w.addNode("text"); + w.setContent("this text is before the node. "); + w.addNode("keepme", "This one we keep...", true ); + w.setContent("this text is after."); + w.addNode("deleteme", "This one we don't...", true ); + w.setContent("this is last..." ); + w.closeNode(); + + //XmlWriter::writeNode( stdout, w.getRoot(), 0, NULL ); + + printf("\n\n"); + + //XmlNode *xNode = w.getRoot()->detatchNode( 1 ); + + //XmlWriter::writeNode( stdout, w.getRoot(), 0, NULL ); + + printf("\n\n"); + + //XmlWriter::writeNode( stdout, xNode, 0, NULL ); + + printf("\n\n"); + + return 0; +} 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 @@ +#include "xmlfilewriter.h" +#include "xmlstringwriter.h" +#include "xmlstringreader.h" + +void fillItIn( XmlWriter &w ) +{ + w.addNode("thinglist"); + + w.addNode("thing"); + w.addProperty("type", " ±î´<M-F6><M-F6>³¸®°êòì¯"); + + w.addNode("id", "Klophin²³±¹¸·µ´äêíëã Staff", true ); + w.addNode("name", "Klophin Staff", true ); + w.addNode("durability", "0.01", true ); + w.addNode("size", "0.1", true ); + + w.addNode("config"); + w.addNode("damage", "3d6+4", true ); + w.addNode("class", "melee", true ); + w.addNode("type", "bludgeon", true ); + w.addNode("damagedesc", "club/clubs", true ); + w.closeNode(); + + w.closeNode(); + + w.closeNode(); +} + +int main() +{ + printf("Testing XmlWriter...\n"); + + //XmlStringReader *xsr = new XmlStringReader("<stuff/>"); + + //printf("%08X\n%08X\n%08X\n", xsr, (XmlReader *)xsr, (XmlDocument *)xsr ); + + //delete (XmlDocument *)xsr; + XmlFileWriter wf("test.xml", "\t"); + + fillItIn( wf ); + + XmlStringWriter ws("\t"); + fillItIn( ws ); + + printf("Now the string version:\n\n%s\n", ws.getString().c_str() ); + + return 0; +} 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 @@ +#include "tokenstring.h" +#include <string.h> + +TokenString::TokenString( const char *lpNewTokenString ) +{ + lpTokenString = NULL; + if( lpNewTokenString ) + { + parseLine( lpNewTokenString ); + } +} + +TokenString::~TokenString() +{ + delete[] lpTokenString; + for( int j = 0; j < lToken.getSize(); j++ ) + { + delete[] (((Token *)lToken[j])->lpToken); + delete ((Token *)lToken[j]); + } +} + +void TokenString::parseLine( const char *lpNewTokenString ) +{ + if( lpTokenString != NULL ) + { + delete[] lpTokenString; + lpTokenString = NULL; + for( int j = 0; j < lToken.getSize(); j++ ) + { + delete[] (((Token *)lToken[j])->lpToken); + delete ((Token *)lToken[j]); + } + lToken.empty(); + } + if( lpNewTokenString == NULL ) + { + lpTokenString = new char[1]; + lpTokenString[0] = '\0'; + lToken.setSize(0); + return; + } + // First order of business, make an internal copy so someone can get it + // if they want to. + int nLen = strlen(lpNewTokenString); + lpTokenString = new char[nLen+1]; + strcpy( lpTokenString, lpNewTokenString ); + + // Now we do a preliminary parse. This could be effected by later + // editing and aliasing, but we'll see... + int nTkStart, nTkEnd; + int mode=0; // 0 = startSearch, 1=endSearch + for( int j = 0; j <= nLen; j++ ) + { + if( mode == 0 ) + { + if( lpTokenString[j] != ' ' && + lpTokenString[j] != '\t' ) + { + nTkStart = j; + mode = 1; + } + } + else + { + if( lpTokenString[j] == ' ' || + lpTokenString[j] == '\t' || + lpTokenString[j] == '\0' ) + { + nTkEnd = j-1; + mode = 0; + + appendToken( nTkStart, nTkEnd ); + } + } + } +} + +void TokenString::appendToken( int nStart, int nEnd ) +{ + Token *pToken = new Token; + pToken->lpOrig = &lpTokenString[nStart]; + + // nStart and nEnd are inclusive, we must add two for the end, and the null + pToken->lpToken = new char[nEnd-nStart+2]; + memcpy( pToken->lpToken, &lpTokenString[nStart], nEnd-nStart+1 ); + pToken->lpToken[nEnd-nStart+1] = '\0'; + +// printf("%s\n", pToken->lpToken ); + lToken.append( pToken ); +} + +void TokenString::insertToken( int nStart, int nEnd, char *lpOldOrig, const char *lpNewToken, int nIndex ) +{ + Token *pToken = new Token; + pToken->lpOrig = lpOldOrig; + + // nStart and nEnd are inclusive, we must add two for the end, and the null + pToken->lpToken = new char[nEnd-nStart+2]; + memcpy( pToken->lpToken, &lpNewToken[nStart], nEnd-nStart+1 ); + pToken->lpToken[nEnd-nStart+1] = '\0'; + + lToken.insertBefore( pToken, nIndex ); +} + +int TokenString::getNumTokens() +{ + return lToken.getSize(); +} + +char *TokenString::getToken( int nIndex ) +{ + if( nIndex >= lToken.getSize() ) return NULL; + return (char *)(((Token *)lToken[nIndex])->lpToken); +} + +char *TokenString::getTokenString( int nIndex ) +{ + if( nIndex >= lToken.getSize() ) return NULL; + return (char *)(((Token *)lToken[nIndex])->lpOrig); +} + +void TokenString::expandTokenTo( int nIndex, char *lpNewToken ) +{ + // First, we delete the token at nIndex, then we keep inserting + // at that position... + // We also have to remember the index to the original string, + // since most of what we're expanding to won't be in the origingal + // we need to keep these indexes updated in order to make other parts + // of the system happy. + char *lpOldOrig = ((Token *)lToken[nIndex])->lpOrig; + delete[] ((Token *)lToken[nIndex])->lpToken; + delete ((Token *)lToken[nIndex]); + lToken.deleteAt( nIndex ); + + // We'll do this just like we did above, but instead we'll + // do tricky things when we find tokens... + int nLen = strlen(lpNewToken); + int nTkStart, nTkEnd, nNewIndex=nIndex; + int mode=0; // 0 = startSearch, 1=endSearch + for( int j = 0; j <= nLen; j++ ) + { + if( mode == 0 ) + { + if( lpNewToken[j] != ' ' && lpNewToken[j] != '\t' ) + { + nTkStart = j; + mode = 1; + } + } + else + { + if( lpNewToken[j] == ' ' || lpNewToken[j] == '\t' || lpNewToken[j] == '\0' ) + { + nTkEnd = j-1; + mode = 0; + + insertToken( nTkStart, nTkEnd, lpOldOrig, lpNewToken, nNewIndex ); + nNewIndex++; + } + } + } +} 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 @@ +#ifndef TOKENSTRING_H +#define TOKENSTRING_H + +#include "linkedlist.h" + +/** A single tokenized command line. Contains all information necesarry to + * nicely access a stand-alone command line and to perform alias expansion + * inside of that command line. + * When expanding a token, the original command line is left intact, so any + * command usng a command line verbatum (getTokenString not getToken) will get + * the original, and not the expanded version. + * Since indexing into the original command line is also done by token, it + * means that using getTokenString( 0 ) will not always get you the first + * character of the command line, it will get you the first non-whitespace + * character. + * Furthermore, when expanding the expantion string is tokenized as well, + * but since the original string is unchanged, all tokens that expand any + * given index will all retain the same index into the original command line. + *@todo Update this to allow it to break on different types of token + * delimiters. + *@author Mike Buland + */ +class TokenString{ +public: + /** Automatically call parseLine when created. + *@param lpNewTokenString The command line to tokenize + *@author Mike Buland + */ + TokenString( const char *lpNewTokenString=NULL ); + virtual ~TokenString(); + + /** Performs a tokenizing parse on the given command line, setting it as + * the internal command line for all future tokenizing (excluding + * expansion) + *@param lpNewTokenString The new command line to set to this object. + *@author Mike Buland + */ + void parseLine( const char *lpNewTokenString ); + + /** Appends a token to the list of available tokens. This references the + * internal pointer to the command line, so no token string must be + * specified. + *@param nStart The first character of the token to insert. + *@param nEnd The last character of the token to insert. + *@author Mike Buland + */ + void appendToken( int nStart, int nEnd ); + + /** Gets the number of tokens. This is particularly useful post-aliasing + * since the number of tokens may not match what is percieved from the + * original command line. + *@returns The number of available tokens. + *@author Mike Buland + */ + int getNumTokens(); + + /** Gets a processed token specified by index. + *@param nIndex The index of the token to retrieve. + *@returns A pointer to the requested token. Please note that these tokens + * may not match the original command line. + *@author Mike Buland + */ + char *getToken( int nIndex ); + + /** Gets the original command line based on tokens. Use this if you want + * to perform your own processing on parts of the command line, without + * resorting to tokens. + * The first character in the returned string will always be + * non-whitespace. + *@param nIndex The index of the token to start at, zero gets you the whole + * command line. + *@returns A pointer to the internal original command line string, starting + * at the position of the first non-whitespace character of the token + * specified. + *@author Mike Buland + */ + char *getTokenString( int nIndex=0 ); + + /** Expands a token, replacing it with the string lpNewToken, but + * processing the new string for tokens before performing the replacement + *@param nIndex Which token should be replaced. + *@param lpNewToken The string to replace the token with. + *@author Mike Buland + */ + void expandTokenTo( int nIndex, char *lpNewToken ); + + /** Inserts a token at any position in the command line. This does not + * effect the original command line. + *@param nStart The start of the token in the string lpNewToken. (inclusive) + *@param nEnd The end of the token in the string lpToken. (inclusive) + *@param lpOldOrig The pointer to the position in the orginal command + * line where this new token should point. + *@param lpNewToken The string containing the new token. May contain more + * than just one token. + *@param nIndex The position to insert the token to. + *@author Mike Buland + */ + void insertToken( int nStart, int nEnd, char *lpOldOrig, const char *lpNewToken, int nIndex ); + +private: + char *lpTokenString; /**< The original text that this string came from */ + LinkedList lToken; /**< The list of tokens. */ + + /** + * A single token within the token string. + */ + typedef struct Token + { + char *lpOrig; /**< This is just a pointer back to lpTokenString */ + char *lpToken; /**< This is really a whole token */ + } Token; +}; + +#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 @@ +#ifndef T_QSORT_H +#define T_QSORT_H + +#define _QSORT_SWAP(a, b, t) ((void)((t = *a), (*a = *b), (*b = t))) + +/* Discontinue quicksort algorithm when partition gets below this size. + This particular magic number was chosen to work best on a Sun 4/260. */ +#define _QSORT_MAX_THRESH 4 + +/* Stack node declarations used to store unfulfilled partition obligations + * (inlined in QSORT). +typedef struct { + QSORT_TYPE *_lo, *_hi; +} qsort_stack_node; + */ + +/* The next 4 #defines implement a very fast in-line stack abstraction. */ +/* The stack needs log (total_elements) entries (we could even subtract + log(MAX_THRESH)). Since total_elements has type unsigned, we get as + upper bound for log (total_elements): + bits per byte (CHAR_BIT) * sizeof(unsigned). */ +#define _QSORT_STACK_SIZE (8 * sizeof(unsigned)) +#define _QSORT_PUSH(top, low, high) \ + (((top->_lo = (low)), (top->_hi = (high)), ++top)) +#define _QSORT_POP(low, high, top) \ + ((--top, (low = top->_lo), (high = top->_hi))) +#define _QSORT_STACK_NOT_EMPTY (_stack < _top) + + +/* Order size using quicksort. This implementation incorporates + four optimizations discussed in Sedgewick: + + 1. Non-recursive, using an explicit stack of pointer that store the + next array partition to sort. To save time, this maximum amount + of space required to store an array of SIZE_MAX is allocated on the + stack. Assuming a 32-bit (64 bit) integer for size_t, this needs + only 32 * sizeof(stack_node) == 256 bytes (for 64 bit: 1024 bytes). + Pretty cheap, actually. + + 2. Chose the pivot element using a median-of-three decision tree. + This reduces the probability of selecting a bad pivot value and + eliminates certain extraneous comparisons. + + 3. Only quicksorts TOTAL_ELEMS / MAX_THRESH partitions, leaving + insertion sort to order the MAX_THRESH items within each partition. + This is a big win, since insertion sort is faster for small, mostly + sorted array segments. + + 4. The larger of the two sub-partitions is always pushed onto the + stack first, with the algorithm then concentrating on the + smaller partition. This *guarantees* no more than log (total_elems) + stack size is needed (actually O(1) in this case)! */ + +/* The main code starts here... */ + +template<typename QSORT_TYPE, typename QSORT_LTT, typename CST> +void tqsort( QSORT_TYPE *QSORT_BASE, int QSORT_NELT ) +{ + QSORT_LTT QSORT_LT; + QSORT_TYPE *const _base = (QSORT_BASE); + const unsigned _elems = (QSORT_NELT); + QSORT_TYPE _hold; + + /* Don't declare two variables of type QSORT_TYPE in a single + * statement: eg `TYPE a, b;', in case if TYPE is a pointer, + * expands to `type* a, b;' wich isn't what we want. + */ + + if (_elems > _QSORT_MAX_THRESH) { + QSORT_TYPE *_lo = _base; + QSORT_TYPE *_hi = _lo + _elems - 1; + struct { + QSORT_TYPE *_hi; QSORT_TYPE *_lo; + } _stack[_QSORT_STACK_SIZE], *_top = _stack + 1; + + while (_QSORT_STACK_NOT_EMPTY) { + QSORT_TYPE *_left_ptr; QSORT_TYPE *_right_ptr; + + /* Select median value from among LO, MID, and HI. Rearrange + LO and HI so the three values are sorted. This lowers the + probability of picking a pathological pivot value and + skips a comparison for both the LEFT_PTR and RIGHT_PTR in + the while loops. */ + + QSORT_TYPE *_mid = _lo + ((_hi - _lo) >> 1); + + if (QSORT_LT ((CST)(_mid), (CST)(_lo))) + _QSORT_SWAP (_mid, _lo, _hold); + if (QSORT_LT ((CST)(_hi), (CST)(_mid))) + _QSORT_SWAP (_mid, _hi, _hold); + else + goto _jump_over; + if (QSORT_LT ((CST)(_mid), (CST)(_lo))) + _QSORT_SWAP (_mid, _lo, _hold); + _jump_over:; + + _left_ptr = _lo + 1; + _right_ptr = _hi - 1; + + /* Here's the famous ``collapse the walls'' section of quicksort. + Gotta like those tight inner loops! They are the main reason + that this algorithm runs much faster than others. */ + do { + while (QSORT_LT ((CST)(_left_ptr), (CST)(_mid))) + ++_left_ptr; + + while (QSORT_LT ((CST)(_mid), (CST)(_right_ptr))) + --_right_ptr; + + if (_left_ptr < _right_ptr) { + _QSORT_SWAP (_left_ptr, _right_ptr, _hold); + if (_mid == _left_ptr) + _mid = _right_ptr; + else if (_mid == _right_ptr) + _mid = _left_ptr; + ++_left_ptr; + --_right_ptr; + } + else if (_left_ptr == _right_ptr) { + ++_left_ptr; + --_right_ptr; + break; + } + } while (_left_ptr <= _right_ptr); + + /* Set up pointers for next iteration. First determine whether + left and right partitions are below the threshold size. If so, + ignore one or both. Otherwise, push the larger partition's + bounds on the stack and continue sorting the smaller one. */ + + if (_right_ptr - _lo <= _QSORT_MAX_THRESH) { + if (_hi - _left_ptr <= _QSORT_MAX_THRESH) + /* Ignore both small partitions. */ + _QSORT_POP (_lo, _hi, _top); + else + /* Ignore small left partition. */ + _lo = _left_ptr; + } + else if (_hi - _left_ptr <= _QSORT_MAX_THRESH) + /* Ignore small right partition. */ + _hi = _right_ptr; + else if (_right_ptr - _lo > _hi - _left_ptr) { + /* Push larger left partition indices. */ + _QSORT_PUSH (_top, _lo, _right_ptr); + _lo = _left_ptr; + } + else { + /* Push larger right partition indices. */ + _QSORT_PUSH (_top, _left_ptr, _hi); + _hi = _right_ptr; + } + } + } + + /* Once the BASE array is partially sorted by quicksort the rest + is completely sorted using insertion sort, since this is efficient + for partitions below MAX_THRESH size. BASE points to the + beginning of the array to sort, and END_PTR points at the very + last element in the array (*not* one beyond it!). */ + + { + QSORT_TYPE *const _end_ptr = _base + _elems - 1; + QSORT_TYPE *_tmp_ptr = _base; + register QSORT_TYPE *_run_ptr; + QSORT_TYPE *_thresh; + + _thresh = _base + _QSORT_MAX_THRESH; + if (_thresh > _end_ptr) + _thresh = _end_ptr; + + /* Find smallest element in first threshold and place it at the + array's beginning. This is the smallest array element, + and the operation speeds up insertion sort's inner loop. */ + + for (_run_ptr = _tmp_ptr + 1; _run_ptr <= _thresh; ++_run_ptr) + if (QSORT_LT ((CST)(_run_ptr), (CST)(_tmp_ptr))) + _tmp_ptr = _run_ptr; + + if (_tmp_ptr != _base) + _QSORT_SWAP (_tmp_ptr, _base, _hold); + + /* Insertion sort, running from left-hand-side + * up to right-hand-side. */ + + _run_ptr = _base + 1; + while (++_run_ptr <= _end_ptr) { + _tmp_ptr = _run_ptr - 1; + while (QSORT_LT ((CST)(_run_ptr), (CST)(_tmp_ptr))) + --_tmp_ptr; + + ++_tmp_ptr; + if (_tmp_ptr != _run_ptr) { + QSORT_TYPE *_trav = _run_ptr + 1; + while (--_trav >= _run_ptr) { + QSORT_TYPE *_hi; QSORT_TYPE *_lo; + _hold = *_trav; + + for (_hi = _lo = _trav; --_lo >= _tmp_ptr; _hi = _lo) + *_hi = *_lo; + *_hi = _hold; + } + } + } + } +} + +#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 @@ +#include <cstdlib> +#include <cstring> +#include <iostream> +#include <cpptest.h> +#include <string.h> +#include <set> +#include <map> + +#include "hashfunctionstring.h" +#include "hashfunctioncasestring.h" +#include "hashfunctionint.h" + +class HashFunctionSuite : public Test::Suite +{ +public: + HashFunctionSuite() + { + TEST_ADD( HashFunctionSuite::functionString ) + TEST_ADD( HashFunctionSuite::functionCaseString ) + TEST_ADD( HashFunctionSuite::functionInt ) + } + +private: + void functionStringWorker( HashFunction &hf, std::set<unsigned long> &sCodes, char *str, int nLevel, int nMax ) + { + for( char let = 'A'; let <= 'z'; let += 3 ) + { + str[nLevel+1] = '\0'; + str[nLevel] = let; + unsigned long x = hf.hash( str ); + TEST_ASSERT( sCodes.find( x ) == sCodes.end() ); + TEST_ASSERT( hf.cmpIDs( str, str ) ); + sCodes.insert( x ); + + if( nLevel < nMax ) + functionStringWorker( hf, sCodes, str, nLevel+1, nMax ); + } + } + + void functionString() + { + HashFunctionString hf; + char str[10]; + + std::set<unsigned long> sCodes; + + functionStringWorker( hf, sCodes, str, 0, 3 ); + } + + void functionCaseStringWorker( HashFunction &hf, std::map<unsigned long, char *> &sCodes, char *str, int nLevel, int nMax ) + { + for( char let = 'A'; let <= 'z'; let += 3 ) + { + str[nLevel+1] = '\0'; + str[nLevel] = let; + unsigned long x = hf.hash( str ); + std::map<unsigned long, char *>::iterator i = sCodes.find( x ); + if( i == sCodes.end() ) + { + sCodes[x] = strdup( str ); + } + else + { + TEST_ASSERT( strcasecmp( (*i).second, str ) == 0 ); + TEST_ASSERT( hf.cmpIDs( (*i).second, str ) == true ); + } + + if( nLevel < nMax ) + functionCaseStringWorker( hf, sCodes, str, nLevel+1, nMax ); + } + } + + void functionCaseString() + { + HashFunctionCaseString hf; + char str[10]; + + std::map<unsigned long, char *> sCodes; + + functionCaseStringWorker( hf, sCodes, str, 0, 3 ); + + std::map<unsigned long, char *>::iterator i; + for( i = sCodes.begin(); i != sCodes.end(); i++ ) + { + free( (*i).second ); + } + } + + void functionInt() + { + HashFunctionInt hf; + + for( long i = -100000; i <= 100000; i += 100 ) + { + TEST_ASSERT( ((long)hf.hash( (void *)i )) == i ); + TEST_ASSERT( ((long)hf.cmpIDs( (void *)i, (void *)i )) ); + } + } +}; + +int main( int argc, char *argv[] ) +{ + Test::TextOutput output( Test::TextOutput::Verbose ); + HashFunctionSuite ts; + return ts.run( output ) ? EXIT_SUCCESS : EXIT_FAILURE; +} + 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 @@ +#include <cstdlib> +#include <cstring> +#include <iostream> +#include <cpptest.h> +#include <string.h> + +#include "xmlstringreader.h" +#include "xmlexception.h" + +class XmlCoreTestSuite : public Test::Suite +{ +public: + XmlCoreTestSuite() + { + TEST_ADD( XmlCoreTestSuite::badXml01 ) + TEST_ADD( XmlCoreTestSuite::badXml02 ) + TEST_ADD( XmlCoreTestSuite::badXml03 ) + + TEST_ADD( XmlCoreTestSuite::entityBuiltin01 ) + + TEST_ADD( XmlCoreTestSuite::entityDoc01 ) + } + +private: + void badXml01() + { + TEST_THROWS( XmlStringReader r("<hello></bye>"), XmlException & ); + } + + void badXml02() + { + TEST_THROWS( XmlStringReader r("<hello>"), XmlException & ); + } + + void badXml03() + { + TEST_THROWS( XmlStringReader r("<hello param=\"stuff?"), XmlException & ); + } + + void entityBuiltin01() + { + XmlStringReader r("<hello>><&'"</hello>"); + TEST_ASSERT( strcmp( r.getRoot()->getContent(), "><&\'\"" ) == 0 ); + } + + void entityDoc01() + { + XmlStringReader r("<!ENTITY name \"bob the man\"><hello>"&name;"</hello>"); + TEST_ASSERT( strcmp( r.getRoot()->getContent(), "\"bob the man\"" ) == 0 ); + } +}; + +int main( int argc, char *argv[] ) +{ + Test::TextOutput output( Test::TextOutput::Verbose ); + XmlCoreTestSuite ts; + return ts.run( output ) ? EXIT_SUCCESS : EXIT_FAILURE; +} + 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 @@ +#include <stdio.h> +#include <stdlib.h> +#include "xmlwriter.h" + +XmlDocument::XmlDocument( XmlNode *pRoot ) +{ + this->pRoot = pRoot; + pCurrent = NULL; + bCompleted = (pRoot!=NULL); +} + +XmlDocument::~XmlDocument() +{ + if( pRoot ) + { + delete pRoot; + } +} + +void XmlDocument::addNode( const char *sName, const char *sContent, bool bClose ) +{ + if( pRoot == NULL ) + { + // This is the first node, so ignore position and just insert it. + pCurrent = pRoot = new XmlNode( sName, NULL, sContent ); + } + else + { + pCurrent = pCurrent->addChild( sName, sContent ); + } + + if( bClose ) + { + closeNode(); + } +} + +void XmlDocument::setName( const char *sName ) +{ + pCurrent->setName( sName ); +} + +bool XmlDocument::isCompleted() +{ + return bCompleted; +} + +XmlNode *XmlDocument::getRoot() +{ + return pRoot; +} + +XmlNode *XmlDocument::detatchRoot() +{ + XmlNode *pTemp = pRoot; + pRoot = NULL; + return pTemp; +} + +XmlNode *XmlDocument::getCurrent() +{ + return pCurrent; +} + +void XmlDocument::closeNode() +{ + if( pCurrent != NULL ) + { + pCurrent = pCurrent->getParent(); + + if( pCurrent == NULL ) + { + bCompleted = true; + } + } +} + +void XmlDocument::addProperty( const char *sName, const char *sValue ) +{ + if( pCurrent ) + { + pCurrent->addProperty( sName, sValue ); + } +} + +void XmlDocument::addProperty( const char *sName, const unsigned char nValue ) +{ + char buf[12]; + sprintf( buf, "%hhi", nValue ); + addProperty( sName, buf ); +} + +void XmlDocument::addProperty( const char *sName, const char nValue ) +{ + char buf[12]; + sprintf( buf, "%hhi", nValue ); + addProperty( sName, buf ); +} + +void XmlDocument::addProperty( const char *sName, const unsigned short nValue ) +{ + char buf[12]; + sprintf( buf, "%hi", nValue ); + addProperty( sName, buf ); +} + +void XmlDocument::addProperty( const char *sName, const short nValue ) +{ + char buf[12]; + sprintf( buf, "%hi", nValue ); + addProperty( sName, buf ); +} + +void XmlDocument::addProperty( const char *sName, const int nValue ) +{ + char buf[12]; + sprintf( buf, "%d", nValue ); + addProperty( sName, buf ); +} + +void XmlDocument::addProperty( const char *sName, const unsigned long nValue ) +{ + char buf[12]; + sprintf( buf, "%li", nValue ); + addProperty( sName, buf ); +} + +void XmlDocument::addProperty( const char *sName, const long nValue ) +{ + char buf[12]; + sprintf( buf, "%li", nValue ); + addProperty( sName, buf ); +} + +void XmlDocument::addProperty( const char *sName, const double dValue ) +{ + char buf[40]; + sprintf( buf, "%f", dValue ); + addProperty( sName, buf ); +} + +void XmlDocument::setContent( const char *sContent ) +{ + if( pCurrent ) + { + pCurrent->setContent( sContent ); + } +} + 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 @@ +#ifndef XMLDOCUMENT +#define XMLDOCUMENT + +#include "xmlnode.h" + +/** + * Keeps track of an easily managed set of XmlNode information. Allows simple + * operations for logical writing to and reading from XML structures. Using + * already formed structures is simply done through the XmlNode structures, + * and the getRoot function here. Creation is performed through a simple set + * of operations that creates the data in a stream type format. + *@author Mike Buland + */ +class XmlDocument +{ +public: + /** + * Construct either a blank XmlDocuemnt or construct a document around an + * existing XmlNode. Be careful, once an XmlNode is passed into a document + * the document takes over ownership and will delete it when the XmlDocument + * is deleted. + *@param pRoot The XmlNode to use as the root of this document, or NULL if + * you want to start a new document. + */ + XmlDocument( XmlNode *pRoot=NULL ); + + /** + * Destroy all contained nodes. + */ + virtual ~XmlDocument(); + + /** + * Add a new node to the document. The new node is appended to the end of + * the current context, i.e. XmlNode, and the new node, provided it isn't + * close as part of this operation, will become the current context. + *@param sName The name of the new node to add. + *@param sContent A content string to be placed inside of the new node. + *@param bClose Set this to true to close the node immediately after adding + * the node and setting the content and name. If this is set to true the + * node is appended, but the context node doesn't change. + */ + void addNode( const char *sName=NULL, const char *sContent=NULL, bool bClose=false ); + + /** + * Set the name of the current node context. + *@param sName The new name of the node. + */ + void setName( const char *sName ); + + /** + * Close the current node context. This will move the current context to + * the parent node of the former current node. If the current node was the + * root then the "completed" flag is set and no more operations are allowed. + */ + void closeNode(); + + /** + * Change the content of the current node at the current position between + * nodes. + *@param sContent The new content of the current node. + */ + void setContent( const char *sContent ); + + /** + * Add a named property to the current context node. + *@param sName The name of the property to add. + *@param sValue The string value of the property. + */ + void addProperty( const char *sName, const char *sValue ); + + /** + * Add a named property to the current context node, converting the + * numerical parameter to text using standrd printf style conversion. + *@param sName The name of the property to add. + *@param nValue The numerical value to add. + */ + void addProperty( const char *sName, const unsigned char nValue ); + + /** + * Add a named property to the current context node, converting the + * numerical parameter to text using standrd printf style conversion. + *@param sName The name of the property to add. + *@param nValue The numerical value to add. + */ + void addProperty( const char *sName, const char nValue ); + + /** + * Add a named property to the current context node, converting the + * numerical parameter to text using standrd printf style conversion. + *@param sName The name of the property to add. + *@param nValue The numerical value to add. + */ + void addProperty( const char *sName, const unsigned short nValue ); + + /** + * Add a named property to the current context node, converting the + * numerical parameter to text using standrd printf style conversion. + *@param sName The name of the property to add. + *@param nValue The numerical value to add. + */ + void addProperty( const char *sName, const short nValue ); + + /** + * Add a named property to the current context node, converting the + * numerical parameter to text using standrd printf style conversion. + *@param sName The name of the property to add. + *@param nValue The numerical value to add. + */ + void addProperty( const char *sName, const unsigned long nValue ); + + /** + * Add a named property to the current context node, converting the + * numerical parameter to text using standrd printf style conversion. + *@param sName The name of the property to add. + *@param nValue The numerical value to add. + */ + void addProperty( const char *sName, const long nValue ); + + /** + * Add a named property to the current context node, converting the + * numerical parameter to text using standrd printf style conversion. + *@param sName The name of the property to add. + *@param nValue The numerical value to add. + */ + void addProperty( const char *sName, const int nValue ); + + /** + * Add a named property to the current context node, converting the + * numerical parameter to text using standrd printf style conversion. + *@param sName The name of the property to add. + *@param dValue The numerical value to add. + */ + void addProperty( const char *sName, const double dValue ); + + /** + * The XmlDocuemnt is considered completed if the root node has been closed. + * Once an XmlDocument has been completed, you can no longer perform + * operations on it. + *@return True if completed, false if still in progress. + */ + bool isCompleted(); + + /** + * Get a pointer to the root object of this XmlDocument. + *@returns A pointer to an internally owned XmlNode. Do not delete this + * XmlNode. + */ + XmlNode *getRoot(); + + /** + * Get a pointer to the root object of this XmlDocument, and remove the + * ownership from this object. + *@returns A pointer to an internally owned XmlNode. Do not delete this + * XmlNode. + */ + XmlNode *detatchRoot(); + + /** + * Get the current context node, which could be the same as the root node. + *@returns A pointer to an internally owned XmlNode. Do not delete this + * XmlNode. + */ + XmlNode *getCurrent(); + +private: + XmlNode *pRoot; /**< The root node. */ + XmlNode *pCurrent; /**< The current node. */ + bool bCompleted; /**< Is it completed? */ +}; + +#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 @@ +#include "xmlfilereader.h" +#include "exceptions.h" +#include <string.h> + +XmlFileReader::XmlFileReader( const char *sFile, bool bStrip ) + : XmlReader( bStrip ) +{ + fh = fopen( sFile, "rt" ); + + if( fh == NULL ) + { + throw XmlException("Couldn't open file: %s", sFile ); + //nError = 1; + } + else + { + buildDoc(); + } +} + +XmlFileReader::~XmlFileReader() +{ +} + +char XmlFileReader::getChar( int nIndex ) +{ + // Make sure we always have a little data left in the buffer + if( fbDataIn.getLength() <= nIndex+1 && fh ) + { + int nBytes = fbDataIn.getCapacity()-1; + char *buf = new char[nBytes]; + int nRead = fread( buf, 1, nBytes, fh ); + fbDataIn.appendData( buf, nRead ); + delete[] buf; + + if( nRead < nBytes ) + { + fclose( fh ); + fh = NULL; + } + } + if( fbDataIn.getLength() >= nIndex+1 ) + { + return fbDataIn.getData()[nIndex]; + } + else + { + throw XmlException("End of XML stream read."); + } +} + +void XmlFileReader::usedChar( int nAmnt ) +{ + if( fbDataIn.getLength()-nAmnt >= 0 ) + { + fbDataIn.usedData( nAmnt ); + } +} 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 @@ +#ifndef XMLFILEREADER +#define XMLFILEREADER + +#include <stdio.h> +#include "xmlreader.h" +#include "flexbuf.h" + +/** + * Takes care of reading in xml formatted data from a file. This could/should + * be made more arbitrary in the future so that we can read the data from any + * source. This is actually made quite simple already since all data read in + * is handled by one single helper function and then palced into a FlexBuf for + * easy access by the other functions. The FlexBuf also allows for block + * reading from disk, which improves speed by a noticable amount. + * <br> + * There are also some extra features implemented that allow you to break the + * standard XML reader specs and eliminate leading and trailing whitespace in + * all read content. This is useful in situations where you allow additional + * whitespace in the files to make them easily human readable. The resturned + * content will be NULL in sitautions where all content between nodes was + * stripped. + *@author Mike Buland + */ +class XmlFileReader : public XmlReader +{ +public: + /** + * Construct an XmlReader around an xml file on your file system. + *@param sFile The file to read. + *@param bStrip Set to true to strip out leading and trailing whitespace in + * node contents. + */ + XmlFileReader( const char *sFile, bool bStrip=false ); + + /** + * Destroy the reader and cleanup. + */ + virtual ~XmlFileReader(); + +private: + char getChar( int nIndex = 0 ); + void usedChar( int nAmnt = 1 ); + FILE *fh; /**< The file handle. */ + FlexBuf fbDataIn; /**< The input buffer. */ +}; + +#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 @@ +#include <stdio.h> +#include <stdlib.h> +#include "xmlfilewriter.h" + +XmlFileWriter::XmlFileWriter( const char *sFileName, const char *sIndent, XmlNode *pRoot ) : + XmlWriter( sIndent, pRoot ) +{ + this->sFileName = sFileName; + fh = fopen( sFileName, "wt"); + fprintf( fh, "<?xml version=\"1.0\"?>\n"); +} + +XmlFileWriter::XmlFileWriter( FILE *fh, const char *sIndent, XmlNode *pRoot ) : + XmlWriter( sIndent, pRoot ), + fh( fh ) +{ +} + +XmlFileWriter::~XmlFileWriter() +{ + fclose( fh ); +} + +void XmlFileWriter::writeString( const char *sString ) +{ + fputs( sString, fh ); +} + 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 @@ +#ifndef XML_FILE_WRITER +#define XML_FILE_WRITER + +#include "xmlnode.h" +#include "xmlwriter.h" + +/** + * Implements xml writing in the XML standard format. Also allows you to + * break that format and auto-indent your exported xml data for ease of + * reading. The auto-indenting will only be applied to sections that + * have no content of their own already. This means that except for + * whitespace all of your data will be preserved perfectly. + * You can create an XmlWriter object around a file, or access the static + * write function directly and just hand it a filename and a root XmlNode. + * When using an XmlWriter object the interface is identicle to that of + * the XmlDocument class, so reference that class for API info. However + * when the initial (or root) node is closed, and the document is finished + * the file will be created and written to automatically. The user can + * check to see if this is actually true by calling the isFinished + * function in the XmlDocument class. + *@author Mike Buland + */ +class XmlFileWriter : public XmlWriter +{ +public: + /** + * Construct a file writer around a given file. + *@param sFileName The file to create or overwrite and write XML into. + *@param sIndent The indent text to use, if any. + */ + XmlFileWriter( const char *sFileName, const char *sIndent=NULL, XmlNode *pRoot=NULL ); + XmlFileWriter( FILE *fh, const char *sIndent=NULL, XmlNode *pRoot=NULL ); + + /** + * Destroy the writer. + */ + virtual ~XmlFileWriter(); + +private: + void writeString( const char *sString ); + std::string sFileName; /**< The filename to write to. */ + FILE *fh; /**< The file handle to the open file. */ +}; + +#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 @@ +#include "xmlnode.h" +#include "hashfunctionstring.h" + +XmlNode::XmlNode( const char *sName, XmlNode *pParent, const char *sContent ) : + hProperties( new HashFunctionString(), 53, false ), + hChildren( new HashFunctionString(), 53, true ) +{ + this->pParent = pParent; + if( sName != NULL ) + { + setName( sName ); + } + if( sContent != NULL ) + { + this->sPreContent = new std::string( sContent ); + } + else + { + this->sPreContent = NULL; + } + nCurContent = 0; +} + +XmlNode::~XmlNode() +{ + for( int j = 0; j < lChildren.getSize(); j++ ) + { + delete (XmlNode *)lChildren[j]; + } + for( int j = 0; j < lPropNames.getSize(); j++ ) + { + delete (std::string *)lPropNames[j]; + } + for( int j = 0; j < lPropValues.getSize(); j++ ) + { + delete (std::string *)lPropValues[j]; + } + for( int j = 0; j < lPostContent.getSize(); j++ ) + { + if( lPostContent[j] != NULL ) + { + delete (std::string *)lPostContent[j]; + } + } + if( sPreContent ) + { + delete sPreContent; + } +} + +void XmlNode::setName( const char *sName ) +{ + if( pParent ) + { + if( this->sName.size() == 0 ) + { + // We're not in the hash yet, so add us + this->sName = sName; + pParent->hChildren.insert( this->sName.c_str(), this ); + } + else + { + // Slightly more tricky, delete us, then add us... + pParent->hChildren.del( this->sName.c_str() ); + this->sName = sName; + pParent->hChildren.insert( this->sName.c_str(), this ); + } + } + else + { + // If we have no parent, then just set the name string, we don't need + // to worry about hashing. + this->sName = sName; + } +} + +void XmlNode::setContent( const char *sContent, int nIndex ) +{ + if( nIndex == -1 ) + { + nIndex = nCurContent; + } + if( nIndex == 0 ) + { + if( this->sPreContent ) + { + delete this->sPreContent; + } + + this->sPreContent = new std::string( sContent ); + } + else + { + nIndex--; + if( lPostContent[nIndex] ) + { + delete (std::string *)lPostContent[nIndex]; + } + + lPostContent.setAt( nIndex, new std::string( sContent ) ); + } +} + +const char *XmlNode::getContent( int nIndex ) +{ + if( nIndex == 0 ) + { + if( sPreContent ) + { + return sPreContent->c_str(); + } + } + else + { + nIndex--; + if( lPostContent[nIndex] ) + { + return ((std::string *)lPostContent[nIndex])->c_str(); + } + } + + return NULL; +} + +XmlNode *XmlNode::addChild( const char *sName, const char *sContent ) +{ + return addChild( new XmlNode( sName, this, sContent ) ); +} + +XmlNode *XmlNode::addChild( XmlNode *pNode ) +{ + lChildren.append( pNode ); + lPostContent.append( NULL ); + nCurContent++; + pNode->pParent = this; + + return pNode; +} + +XmlNode *XmlNode::getParent() +{ + return pParent; +} + +void XmlNode::addProperty( const char *sName, const char *sValue ) +{ + std::string *pName = new std::string( sName ); + std::string *pValue = new std::string( sValue ); + + hProperties.insert( pName->c_str(), pValue->c_str() ); + lPropNames.append( pName ); + lPropValues.append( pValue ); +} + +int XmlNode::getNumProperties() +{ + return lPropNames.getSize(); +} + +const char *XmlNode::getPropertyName( int nIndex ) +{ + std::string *tmp = ((std::string *)lPropNames[nIndex]); + if( tmp == NULL ) + return NULL; + return tmp->c_str(); +} + +const char *XmlNode::getProperty( int nIndex ) +{ + std::string *tmp = ((std::string *)lPropValues[nIndex]); + if( tmp == NULL ) + return NULL; + return tmp->c_str(); +} + +const char *XmlNode::getProperty( const char *sName ) +{ + const char *tmp = (const char *)hProperties[sName]; + if( tmp == NULL ) + return NULL; + return tmp; +} + +void XmlNode::deleteProperty( int nIndex ) +{ + hProperties.del( ((std::string *)lPropNames[nIndex])->c_str() ); + + delete (std::string *)lPropNames[nIndex]; + delete (std::string *)lPropValues[nIndex]; + + lPropNames.deleteAt( nIndex ); + lPropValues.deleteAt( nIndex ); +} + +bool XmlNode::hasChildren() +{ + return lChildren.getSize()>0; +} + +int XmlNode::getNumChildren() +{ + return lChildren.getSize(); +} + +XmlNode *XmlNode::getChild( int nIndex ) +{ + return (XmlNode *)lChildren[nIndex]; +} + +XmlNode *XmlNode::getChild( const char *sName, int nSkip ) +{ + return (XmlNode *)hChildren.get( sName, nSkip ); +} + +const char *XmlNode::getName() +{ + return sName.c_str(); +} + +void XmlNode::deleteNode( int nIndex, const char *sReplacementText ) +{ + XmlNode *xRet = detatchNode( nIndex, sReplacementText ); + + if( xRet != NULL ) + { + delete xRet; + } +} + +XmlNode *XmlNode::detatchNode( int nIndex, const char *sReplacementText ) +{ + if( nIndex < 0 || nIndex >= lChildren.getSize() ) + return NULL; + + // The real trick when deleteing a node isn't actually deleting it, it's + // reforming the content around the node that's now missing...hmmm... + + if( nIndex == 0 ) + { + // If the index is zero we have to deal with the pre-content + if( sReplacementText ) + { + if( sPreContent == NULL ) + { + sPreContent = new std::string( sReplacementText ); + } + else + { + *sPreContent += sReplacementText; + } + } + if( lPostContent.getSize() > 0 ) + { + if( lPostContent[0] != NULL ) + { + if( sPreContent == NULL ) + { + sPreContent = new std::string( + ((std::string *)lPostContent[0])->c_str() + ); + } + else + { + *sPreContent += + ((std::string *)lPostContent[0])->c_str(); + } + } + delete (std::string *)lPostContent[0]; + lPostContent.deleteAt( 0 ); + } + } + else + { + int nCont = nIndex-1; + // If it's above zero we deal with the post-content only + if( sReplacementText ) + { + if( lPostContent[nCont] == NULL ) + { + lPostContent.setAt( nCont, new std::string( sReplacementText ) ); + } + else + { + *((std::string *)lPostContent[nCont]) += sReplacementText; + } + } + if( lPostContent.getSize() > nIndex ) + { + if( lPostContent[nIndex] != NULL ) + { + if( lPostContent[nCont] == NULL ) + { + lPostContent.setAt( nCont, new std::string( + ((std::string *)lPostContent[nIndex])->c_str() + ) ); + } + else + { + *((std::string *)lPostContent[nCont]) += + ((std::string *)lPostContent[nIndex])->c_str(); + } + } + delete (std::string *)lPostContent[nIndex]; + lPostContent.deleteAt( nIndex ); + } + } + + XmlNode *xRet = (XmlNode *)lChildren[nIndex]; + hChildren.del( ((XmlNode *)lChildren[nIndex])->getName() ); + lChildren.deleteAt( nIndex ); + + return xRet; +} + +void XmlNode::replaceNode( int nIndex, XmlNode *pNewNode ) +{ + if( nIndex < 0 || nIndex >= lChildren.getSize() ) + return; //TODO: throw an exception + + delete (XmlNode *)lChildren[nIndex]; + lChildren.setAt( nIndex, pNewNode ); + pNewNode->pParent = this; +} + +XmlNode *XmlNode::getCopy() +{ + XmlNode *pNew = new XmlNode(); + + pNew->sName = sName; + if( sPreContent ) + { + pNew->sPreContent = new std::string( sPreContent->c_str() ); + } + else + { + pNew->sPreContent = NULL; + } + pNew->nCurContent = 0; + + int nSize = lPostContent.getSize(); + pNew->lPostContent.setSize( nSize ); + for( int j = 0; j < nSize; j++ ) + { + if( lPostContent[j] ) + { + pNew->lPostContent.setAt( + j, new std::string( + ((std::string *)lPostContent[j])->c_str() + ) + ); + } + else + { + pNew->lPostContent.setAt( j, NULL ); + } + } + + nSize = lChildren.getSize(); + pNew->lChildren.setSize( nSize ); + for( int j = 0; j < nSize; j++ ) + { + XmlNode *pChild = ((XmlNode *)lChildren[j])->getCopy(); + pNew->lChildren.setAt( j, pChild ); + pChild->pParent = pNew; + pNew->hChildren.insert( pChild->getName(), pChild ); + } + + nSize = lPropNames.getSize(); + pNew->lPropNames.setSize( nSize ); + pNew->lPropValues.setSize( nSize ); + for( int j = 0; j < nSize; j++ ) + { + std::string *pProp = new std::string( ((std::string *)lPropNames[j])->c_str() ); + std::string *pVal = new std::string( ((std::string *)lPropValues[j])->c_str() ); + pNew->lPropNames.setAt( j, pProp ); + pNew->lPropValues.setAt( j, pVal ); + pNew->hProperties.insert( pProp->c_str(), pVal->c_str() ); + pNew->nCurContent++; + } + + return pNew; +} + +void XmlNode::deleteNodeKeepChildren( int nIndex ) +{ + // This is a tricky one...we need to do some patching to keep things all + // even... + XmlNode *xRet = (XmlNode *)lChildren[nIndex]; + + if( xRet == NULL ) + { + return; + } + else + { + if( getContent( nIndex ) ) + { + std::string sBuf( getContent( nIndex ) ); + sBuf += xRet->getContent( 0 ); + setContent( sBuf.c_str(), nIndex ); + } + else + { + setContent( xRet->getContent( 0 ), nIndex ); + } + + int nSize = xRet->lChildren.getSize(); + for( int j = 0; j < nSize; j++ ) + { + XmlNode *pCopy = ((XmlNode *)xRet->lChildren[j])->getCopy(); + pCopy->pParent = this; + lChildren.insertBefore( pCopy, nIndex+j ); + + if( xRet->lPostContent[j] ) + { + lPostContent.insertBefore( + new std::string( ((std::string *)xRet->lPostContent[j])->c_str() ), + nIndex+j + ); + } + else + { + lPostContent.insertBefore( NULL, nIndex+j ); + } + } + + if( getContent( nIndex+nSize ) ) + { + //SString sBuf( getContent( nIndex+nSize ) ); + //sBuf.catfrom( xRet->getContent( nSize ) ); + //setContent( sBuf, nIndex+nSize ); + } + else + { + setContent( xRet->getContent( nSize ), nIndex+nSize ); + } + + deleteNode( nIndex+nSize ); + } +} + +void XmlNode::replaceNodeWithChildren( int nIndex, XmlNode *pNewNode ) +{ +} + 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 @@ +#ifndef XMLNODE +#define XMLNODE + +#include <iostream> +#include "linkedlist.h" +#include "hashtable.h" + +/** + * Maintains all data pertient to an XML node, including sub-nodes and content. + * All child nodes can be accessed through index and through name via a hash + * table. This makes it very easy to gain simple and fast access to all of + * your data. For most applications, the memory footprint is also rather + * small. While XmlNode objects can be used directly to create XML structures + * it is highly reccomended that all operations be performed through the + * XmlDocument class. + *@author Mike Buland + */ +class XmlNode +{ +public: + /** + * Construct a new XmlNode. + *@param sName The name of the node. + *@param pParent The parent node. + *@param sContent The initial content string. + */ + XmlNode( + const char *sName=NULL, + XmlNode *pParent = NULL, + const char *sContent=NULL + ); + + /** + * Delete the node and cleanup all memory. + */ + virtual ~XmlNode(); + + /** + * Change the name of the node. + *@param sName The new name of the node. + */ + void setName( const char *sName ); + + /** + * Construct a new node and add it as a child to this node, also return a + * pointer to the newly constructed node. + *@param sName The name of the new node. + *@param sContent The initial content of the new node. + *@returns A pointer to the newly created child node. + */ + XmlNode *addChild( const char *sName, const char *sContent=NULL ); + + /** + * Add an already created XmlNode as a child to this node. The new child + * XmlNode's parent will be changed appropriately and the parent XmlNode + * will take ownership of the child. + *@param pChild The child XmlNode to add to this XmlNode. + *@returns A pointer to the child node that was just added. + */ + XmlNode *addChild( XmlNode *pChild ); + + /** + * Add a new property to the XmlNode. Properties are name/value pairs. + *@param sName The name of the property. Specifying a name that's already + * in use will overwrite that property. + *@param sValue The textual value of the property. + */ + void addProperty( const char *sName, const char *sValue ); + + /** + * Get a pointer to the parent node, if any. + *@returns A pointer to the node's parent, or NULL if there isn't one. + */ + XmlNode *getParent(); + + /** + * Tells you if this node has children. + *@returns True if this node has at least one child, false otherwise. + */ + bool hasChildren(); + + /** + * Tells you how many children this node has. + *@returns The number of children this node has. + */ + int getNumChildren(); + + /** + * Get a child node at a specific index. + *@param nIndex The zero-based index of the child to retreive. + *@returns A pointer to the child, or NULL if you requested an invalid + * index. + */ + XmlNode *getChild( int nIndex ); + + /** + * Get a child with the specified name, and possibly skip value. For an + * explination of skip values see the HashTable. + *@param sName The name of the child to find. + *@param nSkip The number of nodes with that name to skip. + *@returns A pointer to the child, or NULL if no child with that name was + * found. + */ + XmlNode *getChild( const char *sName, int nSkip=0 ); + + /** + * Get a pointer to the name of this node. Do not change this, use setName + * instead. + *@returns A pointer to the name of this node. + */ + const char *getName(); + + /** + * Set the content of this node, optionally at a specific index. Using the + * default of -1 will set the content after the last added node. + *@param sContent The content string to use. + *@param nIndex The index of the content. + */ + void setContent( const char *sContent, int nIndex=-1 ); + + /** + * Get the content string at a given index, or zero for initial content. + *@param nIndex The index of the content. + *@returns A pointer to the content at that location. + */ + const char *getContent( int nIndex = 0 ); + + /** + * Get the number of properties in this node. + *@returns The number of properties in this node. + */ + int getNumProperties(); + + /** + * Get a property's name by index. + *@param nIndex The index of the property to examine. + *@returns A pointer to the name of the property specified, or NULL if none + * found. + */ + const char *getPropertyName( int nIndex ); + + /** + * Get a proprty's value by index. + *@param nIndex The index of the property to examine. + *@returns A pointer to the value of the property specified, or NULL if none + * found. + */ + const char *getProperty( int nIndex ); + + /** + * Get a propery's value by name. + *@param sName The name of the property to examine. + *@returns A pointer to the value of the property specified, or NULL if none + * found. + */ + const char *getProperty( const char *sName ); + + /** + * Delete a property by index. + *@param nIndex The index of the property to delete. + *@returns True if the property was found and deleted, false if it wasn't + * found. + */ + void deleteProperty( int nIndex ); + + /** + * Delete a child node, possibly replacing it with some text. This actually + * fixes all content strings around the newly deleted child node. + *@param nIndex The index of the node to delete. + *@param sReplacementText The optional text to replace the node with. + *@returns True of the node was found, and deleted, false if it wasn't + * found. + */ + void deleteNode( int nIndex, const char *sReplacementText = NULL ); + + /** + * Delete a given node, but move all of it's children and content up to + * replace the deleted node. All of the content of the child node is + * spliced seamlessly into place with the parent node's content. + *@param nIndex The node to delete. + *@returns True if the node was found and deleted, false if it wasn't. + */ + void deleteNodeKeepChildren( int nIndex ); + + /** + * Detatch a given child node from this node. This effectively works just + * like a deleteNode, except that instead of deleting the node it is removed + * and returned, and all ownership is given up. + *@param nIndex The index of the node to detatch. + *@param sReplacementText The optional text to replace the detatched node + * with. + *@returns A pointer to the newly detatched node, which then passes + * ownership to the caller. + */ + XmlNode *detatchNode( int nIndex, const char *sReplacementText = NULL ); + + /** + * Replace a given node with a different node that is not currently owned by + * this XmlNode or any ancestor. + *@param nIndex The index of the node to replace. + *@param pNewNode The new node to replace the old node with. + *@returns True if the node was found and replaced, false if it wasn't. + */ + void replaceNode( int nIndex, XmlNode *pNewNode ); + + /** + * Replace a given node with the children and content of a given node. + *@param nIndex The index of the node to replace. + *@param pNewNode The node that contains the children and content that will + * replace the node specified by nIndex. + *@returns True if the node was found and replaced, false if it wasn't. + */ + void replaceNodeWithChildren( int nIndex, XmlNode *pNewNode ); + + /** + * Get a copy of this node and all children. getCopy is recursive, so + * beware copying large trees of xml. + *@returns A newly created copy of this node and all of it's children. + */ + XmlNode *getCopy(); + +private: + std::string sName; /**< The name of the node. */ + std::string *sPreContent; /**< The content that goes before any node. */ + LinkedList lChildren; /**< The children. */ + LinkedList lPostContent; /**< The content that comes after children. */ + HashTable hProperties; /**< Property hashtable. */ + HashTable hChildren; /**< Children hashtable. */ + LinkedList lPropNames; /**< List of property names. */ + LinkedList lPropValues; /**< List of property values. */ + XmlNode *pParent; /**< A pointer to the parent of this node. */ + int nCurContent; /**< The current content we're on, for using the -1 on + setContent. */ +}; + +#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 @@ +#include "xmlreader.h" +#include "exceptions.h" +#include <string.h> +#include "hashfunctionstring.h" + +XmlReader::XmlReader( bool bStrip ) : + bStrip( bStrip ), + htEntity( new HashFunctionString(), 11 ) +{ +} + +XmlReader::~XmlReader() +{ + void *i = htEntity.getFirstItemPos(); + while( (i = htEntity.getNextItemPos( i ) ) ) + { + free( (char *)(htEntity.getItemID( i )) ); + delete (StaticString *)htEntity.getItemData( i ); + } +} + +void XmlReader::addEntity( const char *name, const char *value ) +{ + if( htEntity[name] ) return; + + char *sName = strdup( name ); + StaticString *sValue = new StaticString( value ); + + htEntity.insert( sName, sValue ); +} + +#define gcall( x ) if( x == false ) return false; + +bool XmlReader::isws( char chr ) +{ + return ( chr == ' ' || chr == '\t' || chr == '\n' || chr == '\r' ); +} + +bool XmlReader::ws() +{ + while( true ) + { + char chr = getChar(); + if( isws( chr ) ) + { + usedChar(); + } + else + { + return true; + } + } + return true; +} + +bool XmlReader::buildDoc() +{ + // take care of initial whitespace + gcall( ws() ); + textDecl(); + entity(); + addEntity("gt", ">"); + addEntity("lt", "<"); + addEntity("amp", "&"); + addEntity("apos", "\'"); + addEntity("quot", "\""); + gcall( node() ); + + return true; +} + +void XmlReader::textDecl() +{ + if( getChar() == '<' && getChar( 1 ) == '?' ) + { + usedChar( 2 ); + for(;;) + { + if( getChar() == '?' ) + { + if( getChar( 1 ) == '>' ) + { + usedChar( 2 ); + return; + } + } + usedChar(); + } + } +} + +void XmlReader::entity() +{ + for(;;) + { + ws(); + + if( getChar() == '<' && getChar( 1 ) == '!' ) + { + usedChar( 2 ); + ws(); + std::string buf; + for(;;) + { + char chr = getChar(); + usedChar(); + if( isws( chr ) ) break; + buf += chr; + } + + if( strcmp( buf.c_str(), "ENTITY") == 0 ) + { + ws(); + std::string name; + for(;;) + { + char chr = getChar(); + usedChar(); + if( isws( chr ) ) break; + name += chr; + } + ws(); + char quot = getChar(); + usedChar(); + if( quot != '\'' && quot != '\"' ) + { + throw XmlException( + "Only quoted entity values are supported." + ); + } + std::string value; + for(;;) + { + char chr = getChar(); + usedChar(); + if( chr == '&' ) + { + StaticString *tmp = getEscape(); + if( tmp == NULL ) throw XmlException("Entity thing"); + value += tmp->getString(); + delete tmp; + } + else if( chr == quot ) + { + break; + } + else + { + value += chr; + } + } + ws(); + if( getChar() == '>' ) + { + usedChar(); + + addEntity( name.c_str(), value.c_str() ); + } + else + { + throw XmlException( + "Malformed ENTITY: unexpected '%c' found.", + getChar() + ); + } + } + else + { + throw XmlException( + "Unsupported header symbol: %s", + buf.c_str() + ); + } + } + else + { + return; + } + } +} + +bool XmlReader::node() +{ + gcall( startNode() ) + + // At this point, we are closing the startNode + char chr = getChar(); + if( chr == '>' ) + { + usedChar(); + + // Now we process the guts of the node. + gcall( content() ); + } + else if( chr == '/' ) + { + // This is the tricky one, one more validation, then we close the node. + usedChar(); + if( getChar() == '>' ) + { + closeNode(); + usedChar(); + } + else + { + throw XmlException("Close node in singleNode malformed!"); + } + } + else + { + throw XmlException("Close node expected, but not found."); + return false; + } + + return true; +} + +bool XmlReader::startNode() +{ + if( getChar() == '<' ) + { + usedChar(); + + if( getChar() == '/' ) + { + // Heh, it's actually a close node, go figure + FlexBuf fbName; + usedChar(); + gcall( ws() ); + + while( true ) + { + char chr = getChar(); + if( isws( chr ) || chr == '>' ) + { + // Here we actually compare the name we got to the name + // we already set, they have to match exactly. + if( !strcasecmp( getCurrent()->getName(), fbName.getData() ) ) + { + closeNode(); + break; + } + else + { + throw XmlException("Got a mismatched node close tag."); + } + } + else + { + fbName.appendData( chr ); + usedChar(); + } + } + + gcall( ws() ); + if( getChar() == '>' ) + { + // Everything is cool. + usedChar(); + } + else + { + throw XmlException("Got extra junk data instead of node close tag."); + } + } + else + { + // We're good, format is consistant + addNode(); + + // Skip extra whitespace + gcall( ws() ); + gcall( name() ); + gcall( ws() ); + gcall( paramlist() ); + gcall( ws() ); + } + } + else + { + throw XmlException("Expected to find node opening char, '<'."); + } + + return true; +} + +bool XmlReader::name() +{ + FlexBuf fbName; + + while( true ) + { + char chr = getChar(); + if( isws( chr ) || chr == '>' || chr == '/' ) + { + setName( fbName.getData() ); + return true; + } + else + { + fbName.appendData( chr ); + usedChar(); + } + } + + return true; +} + +bool XmlReader::paramlist() +{ + while( true ) + { + char chr = getChar(); + if( chr == '/' || chr == '>' ) + { + return true; + } + else + { + gcall( param() ); + gcall( ws() ); + } + } + + return true; +} + +StaticString *XmlReader::getEscape() +{ + if( getChar( 1 ) == '#' ) + { + // If the entity starts with a # it's a character escape code + int base = 10; + usedChar( 2 ); + if( getChar() == 'x' ) + { + base = 16; + usedChar(); + } + char buf[4]; + int j = 0; + for( j = 0; getChar() != ';'; j++ ) + { + buf[j] = getChar(); + usedChar(); + } + usedChar(); + buf[j] = '\0'; + buf[0] = (char)strtol( buf, (char **)NULL, base ); + buf[1] = '\0'; + + return new StaticString( buf ); + } + else + { + // ...otherwise replace with the appropriate string... + std::string buf; + usedChar(); + for(;;) + { + char cbuf = getChar(); + usedChar(); + if( cbuf == ';' ) break; + buf += cbuf; + } + + StaticString *tmp = (StaticString *)htEntity[buf.c_str()]; + if( tmp == NULL ) return NULL; + + StaticString *ret = new StaticString( *tmp ); + return ret; + } +} + +bool XmlReader::param() +{ + FlexBuf fbName; + FlexBuf fbValue; + + while( true ) + { + char chr = getChar(); + if( isws( chr ) || chr == '=' ) + { + break; + } + else + { + fbName.appendData( chr ); + usedChar(); + } + } + + gcall( ws() ); + + if( getChar() == '=' ) + { + usedChar(); + + gcall( ws() ); + + char chr = getChar(); + if( chr == '"' ) + { + // Better quoted rhs + usedChar(); + + while( true ) + { + chr = getChar(); + if( chr == '"' ) + { + usedChar(); + addProperty( fbName.getData(), fbValue.getData() ); + return true; + } + else + { + if( chr == '&' ) + { + StaticString *tmp = getEscape(); + if( tmp == NULL ) return false; + fbValue.appendData( tmp->getString() ); + delete tmp; + } + else + { + fbValue.appendData( chr ); + usedChar(); + } + } + } + } + else + { + // Simple one-word rhs + while( true ) + { + chr = getChar(); + if( isws( chr ) || chr == '/' || chr == '>' ) + { + addProperty( fbName.getData(), fbValue.getData() ); + return true; + } + else + { + if( chr == '&' ) + { + StaticString *tmp = getEscape(); + if( tmp == NULL ) return false; + fbValue.appendData( tmp->getString() ); + delete tmp; + } + else + { + fbValue.appendData( chr ); + usedChar(); + } + } + } + } + } + else + { + throw XmlException("Expected an equals to seperate the params."); + return false; + } + + return true; +} + +bool XmlReader::content() +{ + FlexBuf fbContent; + + if( bStrip ) gcall( ws() ); + + while( true ) + { + char chr = getChar(); + if( chr == '<' ) + { + if( getChar(1) == '/' ) + { + if( fbContent.getLength() > 0 ) + { + if( bStrip ) + { + int j; + for( j = fbContent.getLength()-1; isws(fbContent.getData()[j]); j-- ); + ((char *)fbContent.getData())[j+1] = '\0'; + } + setContent( fbContent.getData() ); + } + usedChar( 2 ); + gcall( ws() ); + FlexBuf fbName; + while( true ) + { + chr = getChar(); + if( isws( chr ) || chr == '>' ) + { + if( !strcasecmp( getCurrent()->getName(), fbName.getData() ) ) + { + closeNode(); + break; + } + else + { + throw XmlException("Mismatched close tag found: <%s> to <%s>.", getCurrent()->getName(), fbName.getData() ); + } + } + else + { + fbName.appendData( chr ); + usedChar(); + } + } + gcall( ws() ); + if( getChar() == '>' ) + { + usedChar(); + return true; + } + else + { + throw XmlException("Malformed close tag."); + } + } + else if( getChar(1) == '!' ) + { + // We know it's a comment, let's see if it's proper + if( getChar(2) != '-' || + getChar(3) != '-' ) + { + // Not a valid XML comment + throw XmlException("Malformed comment start tag found."); + } + + usedChar( 4 ); + + // Now burn text until we find the close tag + for(;;) + { + if( getChar() == '-' ) + { + if( getChar( 1 ) == '-' ) + { + // The next one has to be a '>' now + if( getChar( 2 ) != '>' ) + { + throw XmlException("Malformed comment close tag found. You cannot have a '--' that isn't followed by a '>' in a comment."); + } + usedChar( 3 ); + break; + } + else + { + // Found a dash followed by a non dash, that's ok... + usedChar( 2 ); + } + } + else + { + // Burn comment chars + usedChar(); + } + } + } + else + { + if( fbContent.getLength() > 0 ) + { + if( bStrip ) + { + int j; + for( j = fbContent.getLength()-1; isws(fbContent.getData()[j]); j-- ); + ((char *)fbContent.getData())[j+1] = '\0'; + } + setContent( fbContent.getData() ); + fbContent.clearData(); + } + gcall( node() ); + } + + if( bStrip ) gcall( ws() ); + } + else if( chr == '&' ) + { + StaticString *tmp = getEscape(); + if( tmp == NULL ) return false; + fbContent.appendData( tmp->getString() ); + delete tmp; + } + else + { + fbContent.appendData( chr ); + usedChar(); + } + } +} + 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 @@ +#ifndef XMLREADER +#define XMLREADER + +#include <stdio.h> +#include "xmldocument.h" +#include "flexbuf.h" +#include "hashtable.h" +#include "staticstring.h" + +/** + * Takes care of reading in xml formatted data from a file. This could/should + * be made more arbitrary in the future so that we can read the data from any + * source. This is actually made quite simple already since all data read in + * is handled by one single helper function and then palced into a FlexBuf for + * easy access by the other functions. The FlexBuf also allows for block + * reading from disk, which improves speed by a noticable amount. + * <br> + * There are also some extra features implemented that allow you to break the + * standard XML reader specs and eliminate leading and trailing whitespace in + * all read content. This is useful in situations where you allow additional + * whitespace in the files to make them easily human readable. The resturned + * content will be NULL in sitautions where all content between nodes was + * stripped. + *@author Mike Buland + */ +class XmlReader : public XmlDocument +{ +public: + /** + * Create a standard XmlReader. The optional parameter bStrip allows you to + * create a reader that will strip out all leading and trailing whitespace + * in content, a-la html. + *@param bStrip Strip out leading and trailing whitespace? + */ + XmlReader( bool bStrip=false ); + + /** + * Destroy this XmlReader. + */ + virtual ~XmlReader(); + + /** + * Build a document based on some kind of input. This is called + * automatically by the constructor. + */ + bool buildDoc(); + +private: + /** + * This is called by the low level automoton in order to get the next + * character. This function should return a character at the current + * position plus nIndex, but does not increment the current character. + *@param nIndex The index of the character from the current stream position. + *@returns A single character at the requested position, or 0 for end of + * stream. + */ + virtual char getChar( int nIndex = 0 ) = 0; + + /** + * Called to increment the current stream position by a single character. + */ + virtual void usedChar( int nAmnt = 1) = 0; + + /** + * Automoton function: is whitespace. + *@param chr A character + *@returns True if chr is whitespace, false otherwise. + */ + bool isws( char chr ); + + /** + * Automoton function: ws. Skips sections of whitespace. + *@returns True if everything was ok, False for end of stream. + */ + bool ws(); + + /** + * Automoton function: node. Processes an XmlNode + *@returns True if everything was ok, False for end of stream. + */ + bool node(); + + /** + * Automoton function: startNode. Processes the begining of a node. + *@returns True if everything was ok, False for end of stream. + */ + bool startNode(); + + /** + * Automoton function: name. Processes the name of a node. + *@returns True if everything was ok, False for end of stream. + */ + bool name(); + + /** + * Automoton function: textDecl. Processes the xml text decleration, if + * there is one. + */ + void textDecl(); + + /** + * Automoton function: entity. Processes an entity from the header. + */ + void entity(); + + /** + * Adds an entity to the list, if it doesn't already exist. + *@param name The name of the entity + *@param value The value of the entity + */ + void addEntity( const char *name, const char *value ); + + StaticString *getEscape(); + + /** + * Automoton function: paramlist. Processes a list of node params. + *@returns True if everything was ok, False for end of stream. + */ + bool paramlist(); + + /** + * Automoton function: param. Processes a single parameter. + *@returns True if everything was ok, False for end of stream. + */ + bool param(); + + /** + * Automoton function: content. Processes node content. + *@returns True if everything was ok, False for end of stream. + */ + bool content(); + + FlexBuf fbContent; /**< buffer for the current node's content. */ + FlexBuf fbParamName; /**< buffer for the current param's name. */ + FlexBuf fbParamValue; /**< buffer for the current param's value. */ + bool bStrip; /**< Are we stripping whitespace? */ + + HashTable htEntity; /**< Entity type definitions. */ +}; + +#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 @@ +#include "xmlstringreader.h" +#include "exceptions.h" +#include <string.h> + +XmlStringReader::XmlStringReader( const char *sString, bool bStrip ) + : XmlReader( bStrip ) +{ + this->sString = sString; + + nIndex = 0; + nLength = strlen( sString ); + + buildDoc(); +} + +XmlStringReader::~XmlStringReader() +{ +} + +char XmlStringReader::getChar( int nAdd ) +{ + if( nLength >= nIndex+nAdd+1 ) + { + return sString[nIndex+nAdd]; + } + else + { + throw XmlException("End of XML stream read."); + } +} + +void XmlStringReader::usedChar( int nAmnt ) +{ + if( nLength >= nIndex+nAmnt ) + { + nIndex += nAmnt; + } +} 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 @@ +#ifndef XMLSTRINGREADER +#define XMLSTRINGREADER + +#include <stdio.h> +#include "xmlreader.h" +#include "flexbuf.h" + +/** + * Takes care of reading in xml formatted data from a file. This could/should + * be made more arbitrary in the future so that we can read the data from any + * source. This is actually made quite simple already since all data read in + * is handled by one single helper function and then palced into a FlexBuf for + * easy access by the other functions. The FlexBuf also allows for block + * reading from disk, which improves speed by a noticable amount. + * <br> + * There are also some extra features implemented that allow you to break the + * standard XML reader specs and eliminate leading and trailing whitespace in + * all read content. This is useful in situations where you allow additional + * whitespace in the files to make them easily human readable. The resturned + * content will be NULL in sitautions where all content between nodes was + * stripped. + *@author Mike Buland + */ +class XmlStringReader : public XmlReader +{ +public: + /** + * Create a new string reader around an already created and formatted + * null-terminated string. + *@param sString A pointer to the string data that will be used. This data + * is not changed during processing. + *@param bStrip Strip out leading and trailing whitespace. + */ + XmlStringReader( const char *sString, bool bStrip=false ); + + /** + * Destroy this string reader. + */ + virtual ~XmlStringReader(); + +private: + char getChar( int nIndex = 0 ); + void usedChar( int nAmnt = 1 ); + const char *sString; /**< Internal pointer to the input string. */ + int nIndex; /**< Our index into the string */ + int nLength; /**< The computed length of the string */ +}; + +#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 @@ +#include <stdio.h> +#include <stdlib.h> +#include "xmlstringwriter.h" + +XmlStringWriter::XmlStringWriter( const char *sIndent ) : + XmlWriter( sIndent ) +{ +} + +XmlStringWriter::~XmlStringWriter() +{ +} + +void XmlStringWriter::writeString( const char *sString ) +{ + sXml += sString; +} + +std::string &XmlStringWriter::getString() +{ + return sXml; +} + 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 @@ +#ifndef XML_STRING_WRITER +#define XML_STRING_WRITER + +#include "xmlnode.h" +#include "xmlwriter.h" + +/** + * Implements xml writing in the XML standard format. Also allows you to + * break that format and auto-indent your exported xml data for ease of + * reading. The auto-indenting will only be applied to sections that + * have no content of their own already. This means that except for + * whitespace all of your data will be preserved perfectly. + * You can create an XmlWriter object around a file, or access the static + * write function directly and just hand it a filename and a root XmlNode. + * When using an XmlWriter object the interface is identicle to that of + * the XmlDocument class, so reference that class for API info. However + * when the initial (or root) node is closed, and the document is finished + * the file will be created and written to automatically. The user can + * check to see if this is actually true by calling the isFinished + * function in the XmlDocument class. + *@author Mike Buland + */ +class XmlStringWriter : public XmlWriter +{ +public: + /** + * Construct a string writer using an internal string buffer. + *@param sIndent Optional indent to add to each line. + */ + XmlStringWriter( const char *sIndent=NULL ); + + /** + * Destroy the string writer and the internal string. + */ + virtual ~XmlStringWriter(); + + /** + * Get the string that was built. This is only valid after the document has + * been completed, so check isCompleted or be sure your addNode and + * closeNode calls match up. + *@returns A reference to the internal string object. + */ + std::string &getString(); + +private: + void writeString( const char *sString ); + std::string sXml; /**< The string object we "write" to. */ +}; + +#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 @@ +#include <stdio.h> +#include <stdlib.h> +#include "xmlwriter.h" + +XmlWriter::XmlWriter( const char *sIndent, XmlNode *pRoot ) : + XmlDocument( pRoot ) +{ + if( sIndent == NULL ) + { + this->sIndent = ""; + } + else + { + this->sIndent = sIndent; + } +} + +XmlWriter::~XmlWriter() +{ +} + +void XmlWriter::write() +{ + write( getRoot(), sIndent.c_str() ); +} + +void XmlWriter::write( XmlNode *pRoot, const char *sIndent ) +{ + writeNode( pRoot, 0, sIndent ); +} + +void XmlWriter::closeNode() +{ + XmlDocument::closeNode(); + + if( isCompleted() ) + { + write( getRoot(), sIndent.c_str() ); + } +} + +void XmlWriter::writeIndent( int nIndent, const char *sIndent ) +{ + if( sIndent == NULL ) return; + for( int j = 0; j < nIndent; j++ ) + { + writeString( sIndent ); + } +} + +std::string XmlWriter::escape( std::string sIn ) +{ + std::string sOut; + + std::string::const_iterator i; + for( i = sIn.begin(); i != sIn.end(); i++ ) + { + if( ((*i >= ' ' && *i <= '9') || + (*i >= 'a' && *i <= 'z') || + (*i >= 'A' && *i <= 'Z') ) && + (*i != '\"' && *i != '\'' && *i != '&') + ) + { + sOut += *i; + } + else + { + sOut += "&#"; + char buf[4]; + sprintf( buf, "%u", (unsigned char)*i ); + sOut += buf; + sOut += ';'; + } + } + + return sOut; +} + +void XmlWriter::writeNodeProps( XmlNode *pNode, int nIndent, const char *sIndent ) +{ + for( int j = 0; j < pNode->getNumProperties(); j++ ) + { + writeString(" "); + writeString( pNode->getPropertyName( j ) ); + writeString("=\""); + writeString( escape( pNode->getProperty( j ) ).c_str() ); + writeString("\""); + } +} + +void XmlWriter::writeNode( XmlNode *pNode, int nIndent, const char *sIndent ) +{ + if( pNode->hasChildren() ) + { + writeIndent( nIndent, sIndent ); + writeString("<"); + writeString( pNode->getName() ); + writeNodeProps( pNode, nIndent, sIndent ); + if( sIndent ) + writeString(">\n"); + else + writeString(">"); + + if( pNode->getContent( 0 ) ) + { + writeIndent( nIndent+1, sIndent ); + if( sIndent ) + { + writeString( pNode->getContent( 0 ) ); + writeString("\n"); + } + else + writeString( pNode->getContent( 0 ) ); + } + + int nNumChildren = pNode->getNumChildren(); + for( int j = 0; j < nNumChildren; j++ ) + { + writeNode( pNode->getChild( j ), nIndent+1, sIndent ); + if( pNode->getContent( j+1 ) ) + { + writeIndent( nIndent+1, sIndent ); + if( sIndent ) + { + writeString( pNode->getContent( j+1 ) ); + writeString("\n"); + } + else + writeString( pNode->getContent( j+1 ) ); + } + } + + writeIndent( nIndent, sIndent ); + if( sIndent ) + { + writeString("</"); + writeString( pNode->getName() ); + writeString(">\n"); + } + else + { + writeString("</"); + writeString( pNode->getName() ); + writeString(">"); + } + } + else if( pNode->getContent() ) + { + writeIndent( nIndent, sIndent ); + writeString("<"); + writeString( pNode->getName() ); + writeNodeProps( pNode, nIndent, sIndent ); + writeString(">"); + writeString( pNode->getContent() ); + writeString("</"); + writeString( pNode->getName() ); + writeString(">"); + if( sIndent ) + writeString("\n"); + } + else + { + writeIndent( nIndent, sIndent ); + writeString("<"); + writeString( pNode->getName() ); + writeNodeProps( pNode, nIndent, sIndent ); + if( sIndent ) + writeString("/>\n"); + else + writeString("/>"); + } +} + 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 @@ +#ifndef XMLWRITER +#define XMLWRITER + +#include "xmlnode.h" +#include "xmldocument.h" + +/** + * Implements xml writing in the XML standard format. Also allows you to + * break that format and auto-indent your exported xml data for ease of + * reading. The auto-indenting will only be applied to sections that + * have no content of their own already. This means that except for + * whitespace all of your data will be preserved perfectly. + * You can create an XmlWriter object around a file, or access the static + * write function directly and just hand it a filename and a root XmlNode. + * When using an XmlWriter object the interface is identicle to that of + * the XmlDocument class, so reference that class for API info. However + * when the initial (or root) node is closed, and the document is finished + * the file will be created and written to automatically. The user can + * check to see if this is actually true by calling the isFinished + * function in the XmlDocument class. + *@author Mike Buland + */ +class XmlWriter : public XmlDocument +{ +public: + /** + * Construct a standard XmlWriter. + *@param sIndent Set this to something other than NULL to include it as an + * indent before each node in the output that doesn't already have content. + * If you are using the whitespace stripping option in the XmlReader and set + * this to a tab or some spaces it will never effect the content of your + * file. + */ + XmlWriter( const char *sIndent=NULL, XmlNode *pRoot=NULL ); + + /** + * Destroy the writer. + */ + virtual ~XmlWriter(); + + /** + * This override of the parent class closeNode function calls the parent + * class, but also triggers a write operation when the final node is closed. + * This means that by checking the isCompleted() function the user may also + * check to see if their file has been written or not. + */ + void closeNode(); + + void write(); + +private: + std::string sIndent; /**< The indent string */ + + std::string escape( std::string sIn ); + + /** + * Write the file. + *@param pNode The root node + *@param sIndent The indent text. + */ + void write( XmlNode *pNode, const char *sIndent=NULL ); + + /** + * Write a node in the file, including children. + *@param pNode The node to write. + *@param nIndent The indent level (the number of times to include sIndent) + *@param sIndent The indent text. + */ + void writeNode( XmlNode *pNode, int nIndent, const char *sIndent ); + + /** + * Write the properties of a node. + *@param pNode The node who's properties to write. + *@param nIndent The indent level of the containing node + *@param sIndent The indent text. + */ + void writeNodeProps( XmlNode *pNode, int nIndent, const char *sIndent ); + + /** + * Called to write the actual indent. + *@param nIndent The indent level. + *@param sIndent The indent text. + */ + void writeIndent( int nIndent, const char *sIndent ); + + /** + * This is the function that must be overridden in order to use this class. + * It must write the null-terminated string sString, minus the mull, + * verbatum to it's output device. Adding extra characters for any reason + * will break the XML formatting. + *@param sString The string data to write to the output. + */ + virtual void writeString( const char *sString ) = 0; +}; + +#endif diff --git a/src/ordhash.cpp b/src/ordhash.cpp deleted file mode 100644 index 77cbd61..0000000 --- a/src/ordhash.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "ordhash.h" diff --git a/src/ordhash.h b/src/ordhash.h deleted file mode 100644 index e946f95..0000000 --- a/src/ordhash.h +++ /dev/null @@ -1,104 +0,0 @@ -#ifndef ORD_HASH_H -#define ORD_HASH_H - -#include "hash.h" -#include "tqsort.h" - -template<typename key, typename value, typename cmpfnc, typename sizecalc = __calcNextTSize_fast, typename keyalloc = std::allocator<key>, typename valuealloc = std::allocator<value>, typename challoc = std::allocator<uint32_t> > -class OrdHash : public Hash<key, value, sizecalc, keyalloc, valuealloc, challoc> -{ -public: - OrdHash() : - bSorted( false ), - aData( NULL ) - { - } - - virtual ~OrdHash() - { - } - -protected: - virtual void invalidate() - { - bSorted = false; - delete[] aData; - aData = NULL; - } - - virtual void onInsert() - { - invalidate(); - } - - virtual void onUpdate() - { - invalidate(); - } - - virtual void onDelete() - { - invalidate(); - } - - virtual void onReHash() - { - invalidate(); - } - - virtual std::pair<key,value> getAtPos( uint32_t nPos ) - { - return Hash<key, value, sizecalc, keyalloc, valuealloc, challoc>::getAtPos( aData[nPos].nIndex ); - } - - virtual void buildIndex() - { - aData = new struct ind[this->nFilled]; - uint32_t k = 0; - for( uint32_t j = 0; j < this->nCapacity; j++ ) - { - if( this->isFilled( j ) ) - { - if( !this->isDeleted( j ) ) - { - aData[k].pVal = &(this->aValues[j]); - aData[k].nIndex = j; - k++; - } - } - } - - tqsort<typename OrdHash<key, value, cmpfnc, sizecalc, keyalloc, valuealloc, challoc>::ind, cmpfnc, value **>( aData, this->nFilled ); - - bSorted = true; - } - - virtual uint32_t getFirstPos( bool &bFinished ) - { - if( bSorted == false ) - buildIndex(); - - return 0; - } - - virtual uint32_t getNextPos( uint32_t nPos, bool &bFinished ) - { - if( nPos+1 >= this->nFilled ) - { - bFinished = true; - return 0; - } - return ++nPos; - } -public: - typedef struct ind - { - value *pVal; - uint32_t nIndex; - } ind; -private: - bool bSorted; - ind *aData; -}; - -#endif diff --git a/src/paramproc.cpp b/src/paramproc.cpp deleted file mode 100644 index a352e66..0000000 --- a/src/paramproc.cpp +++ /dev/null @@ -1,514 +0,0 @@ -#include "paramproc.h" -#include <stdio.h> - -#define ptrtype( iitype, iiname ) \ - ParamProc::ParamPtr::ParamPtr( iitype *iiname ) : \ - type( vt ##iiname ) { val.iiname = iiname; } - -ParamProc::ParamPtr::ParamPtr() -{ - val.str = NULL; - type = vtunset; -} - -ptrtype( std::string, str ); -ptrtype( uint64_t, uint64 ); -ptrtype( uint32_t, uint32 ); -ptrtype( uint16_t, uint16 ); -ptrtype( uint8_t, uint8 ); -ptrtype( int64_t, int64 ); -ptrtype( int32_t, int32 ); -ptrtype( int16_t, int16 ); -ptrtype( int8_t, int8 ); -ptrtype( float, float32 ); -ptrtype( double, float64 ); -ptrtype( long double, float96 ); -ptrtype( bool, bln ); - -ParamProc::ParamPtr &ParamProc::ParamPtr::operator=( ParamProc::ParamPtr &ptr ) -{ - val = ptr.val; - type = ptr.type; - - return *this; -} - -bool ParamProc::ParamPtr::isSet() -{ - return type != vtunset; -} - -ParamProc::ParamPtr &ParamProc::ParamPtr::operator=( const char *str ) -{ - if( !isSet() ) return *this; - switch( type ) - { - case vtstr: - (*val.str) = str; - break; - - case vtuint64: - (*val.uint64) = strtoull( str, NULL, 10 ); - break; - - case vtuint32: - (*val.uint32) = strtoul( str, NULL, 10 ); - break; - - case vtuint16: - (*val.uint16) = (uint16_t)strtoul( str, NULL, 10 ); - break; - - case vtuint8: - (*val.uint8) = (uint8_t)strtoul( str, NULL, 10 ); - break; - - case vtint64: - (*val.int64) = strtoll( str, NULL, 10 ); - break; - - case vtint32: - (*val.int32) = strtol( str, NULL, 10 ); - break; - - case vtint16: - (*val.int16) = (int16_t)strtol( str, NULL, 10 ); - break; - - case vtint8: - (*val.int8) = (int8_t)strtol( str, NULL, 10 ); - break; - - case vtfloat32: - (*val.float32) = strtof( str, NULL ); - break; - - case vtfloat64: - (*val.float64) = strtod( str, NULL ); - break; - - case vtfloat96: - (*val.float96) = strtold( str, NULL ); - break; - - case vtbln: - if( strcasecmp("yes", str ) == 0 || - strcasecmp("true", str ) == 0 ) - { - (*val.bln) = true; - } - else - { - (*val.bln) = false; - } - break; - } - - return *this; -} - -ParamProc::ParamProc() -{ -} - -ParamProc::~ParamProc() -{ - for( std::list<ArgSpec *>::iterator i = lArg.begin(); - i != lArg.end(); i++ ) - { - delete *i; - } - - for( std::list<Banner *>::iterator i = lBan.begin(); - i != lBan.end(); i++ ) - { - delete *i; - } - -} -/* -void ParamProc::addParam( const char *lpWord, char cChar, Proc proc, ParamPtr val ) -{ - printf("Calling callback...\n"); - val = "Hello there, this is set in the ParamProc"; - (this->*proc)(); -}*/ - -void ParamProc::addParam( const char *lpWord, char cChar, Proc proc, - ParamPtr val, const char *lpDesc, const char *lpExtra, - const char *lpValue ) -{ - ArgSpec *as = new ArgSpec; - if( lpWord ) - as->sWord = lpWord; - - as->cChar = cChar; - as->proc = proc; - as->val = val; - if( lpDesc ) - as->sDesc = lpDesc; - if( lpExtra ) - as->sExtra = lpExtra; - if( lpValue ) - as->sValue = lpValue; - - lArg.push_back( as ); - - if( !lBan.empty() ) - { - if( lBan.back()->pBefore == NULL ) - lBan.back()->pBefore = as; - } -} - -void ParamProc::addParam( const char *lpWord, char cChar, Proc proc, - const char *lpDesc, const char *lpExtra, - const char *lpValue ) -{ - addParam( lpWord, cChar, proc, ParamPtr(), lpDesc, lpExtra, lpValue ); -} - -void ParamProc::addParam( const char *lpWord, char cChar, ParamPtr val, - const char *lpDesc, const char *lpExtra, - const char *lpValue ) -{ - addParam( lpWord, cChar, NULL, val, lpDesc, lpExtra, lpValue ); -} - -void ParamProc::addParam( const char *lpWord, Proc proc, ParamPtr val, - const char *lpDesc, const char *lpExtra, - const char *lpValue ) -{ - addParam( lpWord, '\0', proc, val, lpDesc, lpExtra, lpValue ); -} - -void ParamProc::addParam( const char *lpWord, Proc proc, - const char *lpDesc, const char *lpExtra, - const char *lpValue ) -{ - addParam( lpWord, '\0', proc, ParamPtr(), lpDesc, lpExtra, lpValue ); -} - -void ParamProc::addParam( const char *lpWord, ParamPtr val, - const char *lpDesc, const char *lpExtra, - const char *lpValue ) -{ - addParam( lpWord, '\0', NULL, val, lpDesc, lpExtra, lpValue ); -} - -void ParamProc::addParam( char cChar, Proc proc, ParamPtr val, - const char *lpDesc, const char *lpExtra, - const char *lpValue ) -{ - addParam( NULL, cChar, proc, val, lpDesc, lpExtra, lpValue ); -} - -void ParamProc::addParam( char cChar, Proc proc, - const char *lpDesc, const char *lpExtra, - const char *lpValue ) -{ - addParam( NULL, cChar, proc, ParamPtr(), lpDesc, lpExtra, lpValue ); -} - -void ParamProc::addParam( char cChar, ParamPtr val, - const char *lpDesc, const char *lpExtra, - const char *lpValue ) -{ - addParam( NULL, cChar, NULL, val, lpDesc, lpExtra, lpValue ); -} - -void ParamProc::process( int argc, char *argv[] ) -{ - for( int arg = 1; arg < argc; arg++ ) - { - //printf(":::%d:::%s\n", arg, argv[arg] ); - if( argv[arg][0] == '-' ) - { - if( argv[arg][1] == '-' ) - { - ArgSpec *s = checkWord( argv[arg]+2 ); - if( s ) - { - if( argv[arg][s->sWord.getLength()+2] == '=' ) - { - if( s->val.isSet() ) - { - if( s->sValue.getString() == NULL ) - { - s->val = argv[arg]+s->sWord.getLength()+3; - } - else - { - s->val = s->sValue.getString(); - } - } - if( s->proc ) - { - char **tmp = new char*[argc-arg]; - tmp[0] = argv[arg]+s->sWord.getLength()+3; - for( int k = 1; k < argc-arg; k++ ) - tmp[k] = argv[arg+k]; - int ret = (this->*s->proc)( argc-arg, tmp ); - if( ret > 0 ) - { - arg += ret-1; - } - delete tmp; - } - } - else - { - int add = 0; - if( s->val.isSet() ) - { - if( s->sValue.getString() == NULL ) - { - if( arg+1 >= argc ) - { - return; - } - s->val = argv[arg+1]; - add++; - } - else - { - s->val = s->sValue.getString(); - } - } - if( s->proc ) - { - int ret = (this->*s->proc)( - argc-arg-1, argv+arg+1 ); - - if( ret > add ) - add = 0; - else - add -= ret; - arg += ret; - } - arg += add; - } - continue; - } - else - { - unknownParam( argc-arg, argv+arg ); - } - } - else - { - for( int chr = 1; argv[arg][chr]; chr++ ) - { - ArgSpec *s = checkLetr( argv[arg][chr] ); - if( s ) - { - if( argv[arg][chr+1] != '\0' ) - { - bool bUsed = false; - if( s->val.isSet() ) - { - if( s->sValue.getString() == NULL ) - { - s->val = argv[arg]+chr+1; - bUsed = true; - } - else - { - s->val = s->sValue.getString(); - } - } - if( s->proc ) - { - char **tmp = new char*[argc-arg]; - tmp[0] = argv[arg]+chr+1; - for( int k = 1; k < argc-arg; k++ ) - tmp[k] = argv[arg+k]; - int ret = (this->*s->proc)( argc-arg, tmp ); - if( ret > 0 ) - { - arg += ret - 1; - delete tmp; - break; - } - delete tmp; - } - if( bUsed ) - { - break; - } - } - else - { - bool bUsed = false; - if( s->val.isSet() ) - { - if( s->sValue.getString() == NULL ) - { - s->val = argv[arg+1]; - bUsed = true; - } - else - { - s->val = s->sValue.getString(); - } - } - if( s->proc ) - { - int ret = (this->*s->proc)( - argc-arg-1, argv+arg+1 - ); - if( ret > 0 ) - { - arg += ret; - break; - } - } - if( bUsed ) - { - arg++; - break; - } - } - } - else - { - unknownParam( argc-arg, argv+arg ); - } - } - } - } - else - { - cmdParam( argc-arg, argv+arg ); - } - } -} - -ParamProc::ArgSpec *ParamProc::checkWord( const char *arg ) -{ - //printf("Checking \"%s\"...\n", arg ); - std::list<ArgSpec *>::const_iterator i; - for( i = lArg.begin(); i != lArg.end(); i++ ) - { - if( (*i)->sWord.getString() == NULL ) - continue; - - if( !strcmp( (*i)->sWord, arg ) ) - return *i; - - if( (*i)->val.isSet() ) - { - if( !strncmp( (*i)->sWord, arg, (*i)->sWord.getLength() ) && - arg[(*i)->sWord.getLength()] == '=' ) - { - return *i; - } - } - } - - return NULL; -} - -ParamProc::ArgSpec *ParamProc::checkLetr( const char arg ) -{ - //printf("Checking \'%c\'...\n", arg ); - std::list<ArgSpec *>::const_iterator i; - for( i = lArg.begin(); i != lArg.end(); i++ ) - { - if( (*i)->cChar == '\0' ) - continue; - - if( (*i)->cChar == arg ) - { - return *i; - } - } - - return NULL; -} - -int ParamProc::cmdParam( int argc, char *argv[] ) -{ - printf("Unhandled command parameter \"%s\" found!\n", argv[0] ); - return 0; -} - -int ParamProc::unknownParam( int argc, char *argv[] ) -{ - printf("Unknown parameter \"%s\" found!\n", argv[0] ); - return 0; -} - -int ParamProc::help( int argc, char *argv[] ) -{ - std::list<Banner *>::const_iterator b = lBan.begin(); - std::list<ArgSpec *>::const_iterator i; - int len=0; - for( i = lArg.begin(); i != lArg.end(); i++ ) - { - if( len < (*i)->sWord.getLength() + (*i)->sExtra.getLength() ) - len = (*i)->sWord.getLength() + (*i)->sExtra.getLength(); - } - char fmt[10]; - sprintf( fmt, "%%-%ds ", len ); - - for( i = lArg.begin(); i != lArg.end(); i++ ) - { - if( b != lBan.end() ) - { - if( (*b)->pBefore == (*i) ) - { - printf( (*b)->sBanner.getString() ); - b++; - } - } - printf(" "); - if( (*i)->cChar ) - { - if( (*i)->sWord.getString() ) - { - printf("-%c, ", (*i)->cChar ); - } - else - { - printf("-%c ", (*i)->cChar ); - } - } - else - { - printf(" "); - } - if( (*i)->sWord.getString() ) - { - printf("--"); - std::string sTmp = (*i)->sWord.getString(); - if( (*i)->sExtra.getString() ) - sTmp += (*i)->sExtra.getString(); - printf( fmt, sTmp.c_str() ); - } - else - { - printf(" "); - printf(fmt, "" ); - } - printf("%s\n", (*i)->sDesc.getString() ); - } - if( b != lBan.end() ) - { - if( (*b)->pBefore == NULL ) - { - printf( (*b)->sBanner.getString() ); - } - } - - exit( 0 ); -} - -void ParamProc::addHelpBanner( const char *sHelpBanner ) -{ - Banner *pBan = new Banner; - pBan->sBanner = sHelpBanner; - pBan->pBefore = NULL; - lBan.push_back( pBan ); -} - diff --git a/src/paramproc.h b/src/paramproc.h deleted file mode 100644 index d857193..0000000 --- a/src/paramproc.h +++ /dev/null @@ -1,153 +0,0 @@ -#ifndef PARAM_PROC_H -#define PARAM_PROC_H - -#include <stdint.h> -#include <string> -#include <list> -#include "staticstring.h" - -class ParamProc -{ -public: - class ParamPtr - { - public: - ParamPtr(); - ParamPtr( std::string *str ); - ParamPtr( uint64_t *uint64 ); - ParamPtr( uint32_t *uint32 ); - ParamPtr( uint16_t *uint16 ); - ParamPtr( uint8_t *uint8 ); - ParamPtr( int64_t *int64 ); - ParamPtr( int32_t *int32 ); - ParamPtr( int16_t *int16 ); - ParamPtr( int8_t *int8 ); - ParamPtr( float *float32 ); - ParamPtr( double *float64 ); - ParamPtr( long double *float96 ); - ParamPtr( bool *bln ); - - enum - { - vtunset, - vtstr, - vtuint64, - vtuint32, - vtuint16, - vtuint8, - vtint64, - vtint32, - vtint16, - vtint8, - vtfloat32, - vtfloat64, - vtfloat96, - vtbln, - }; - ParamPtr &operator=( ParamPtr &ptr ); - ParamPtr &operator=( const char *str ); - - bool isSet(); - - private: - int type; - union - { - std::string *str; - uint64_t *uint64; - uint32_t *uint32; - uint16_t *uint16; - uint8_t *uint8; - int64_t *int64; - int32_t *int32; - int16_t *int16; - int8_t *int8; - float *float32; - double *float64; - long double *float96; - bool *bln; - } val; - }; - - typedef int (ParamProc::*Proc)( int, char *[] ); - - typedef struct ArgSpec - { - uint8_t nFlags; - StaticString sWord; - char cChar; - Proc proc; - ParamProc::ParamPtr val; - StaticString sExtra; - StaticString sDesc; - StaticString sValue; - } ArgSpec; - -public: - ParamProc(); - virtual ~ParamProc(); - - void addParam( const char *lpWord, char cChar, Proc proc, ParamPtr val, - const char *lpDesc=NULL, const char *lpExtra=NULL, - const char *lpValue=NULL - ); - void addParam( const char *lpWord, char cChar, Proc proc, - const char *lpDesc=NULL, const char *lpExtra=NULL, - const char *lpValue=NULL - ); - void addParam( const char *lpWord, char cChar, ParamPtr val, - const char *lpDesc=NULL, const char *lpExtra=NULL, - const char *lpValue=NULL - ); - - void addParam( const char *lpWord, Proc proc, ParamPtr val, - const char *lpDesc=NULL, const char *lpExtra=NULL, - const char *lpValue=NULL - ); - void addParam( const char *lpWord, Proc proc, - const char *lpDesc=NULL, const char *lpExtra=NULL, - const char *lpValue=NULL - ); - void addParam( const char *lpWord, ParamPtr val, - const char *lpDesc=NULL, const char *lpExtra=NULL, - const char *lpValue=NULL - ); - - void addParam( char cChar, Proc proc, ParamPtr val, - const char *lpDesc=NULL, const char *lpExtra=NULL, - const char *lpValue=NULL - ); - void addParam( char cChar, Proc proc, - const char *lpDesc=NULL, const char *lpExtra=NULL, - const char *lpValue=NULL - ); - void addParam( char cChar, ParamPtr val, - const char *lpDesc=NULL, const char *lpExtra=NULL, - const char *lpValue=NULL - ); - - void process( int argc, char *argv[] ); - void addHelpBanner( const char *sHelpBanner ); - -private: - ArgSpec *checkWord( const char *arg ); - ArgSpec *checkLetr( const char arg ); - -public: - virtual int cmdParam( int argc, char *argv[] ); - virtual int unknownParam( int argc, char *argv[] ); - virtual int help( int argc, char *argv[] ); - -private: - typedef struct Banner - { - StaticString sBanner; - ArgSpec *pBefore; - } Banner; - std::list<Banner *> lBan; - std::list<ArgSpec *> lArg; -}; - -#define mkproc( cls ) static_cast<int (ParamProc::*)( int, char *[])>(&cls) - -#endif diff --git a/src/plugger.cpp b/src/plugger.cpp deleted file mode 100644 index f3bfa67..0000000 --- a/src/plugger.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "plugger.h" diff --git a/src/plugger.h b/src/plugger.h deleted file mode 100644 index d92f194..0000000 --- a/src/plugger.h +++ /dev/null @@ -1,198 +0,0 @@ -#ifndef PLUGGER_H -#define PLUGGER_H - - -#include "hashtable.h" -#include "list" -#include "hashfunctionstring.h" -#include "hashfunctionint.h" -#include "dlfcn.h" -#include "exceptions.h" - -typedef struct PluginInfo -{ - const char *sID; - const char *sAuthor; - unsigned short nVersion; - unsigned short nRevision; - void *(*createPlugin)(); - void (*destroyPlugin)( void * ); -} PluginInfo; - -typedef struct PluginReg -{ - bool bBuiltin; - void *dlHandle; - PluginInfo *pInfo; -} PluginReg; - -#define PluginInterface( classname, baseclass, name, ver, rev ) \ -extern "C" { \ - baseclass *create ##classname() \ - { \ - return new classname(); \ - } \ - void destroy ##classname( baseclass *pCls ) \ - { \ - delete pCls; \ - } \ - PluginInfo classname = { \ - #classname, name, ver, rev, \ - create ##classname, destroy ##classname }; \ -} - -#define PluginInterface2( pluginname, classname, baseclass, name, ver, rev ) \ -extern "C" { \ - baseclass *create ##classname() \ - { \ - return new classname(); \ - } \ - void destroy ##classname( baseclass *pCls ) \ - { \ - delete pCls; \ - } \ - PluginInfo pluginname = { \ - #pluginname, name, ver, rev, \ - (void *(*)())(create ##classname), \ - (void (*)( void * ))(destroy ##classname) }; \ -} - -#define PluginInterface3( structname, pluginname, classname, baseclass, name, ver, rev ) \ -extern "C" { \ - baseclass *create ##classname() \ - { \ - return new classname(); \ - } \ - void destroy ##classname( baseclass *pCls ) \ - { \ - delete pCls; \ - } \ - PluginInfo structname = { \ - #pluginname, name, ver, rev, \ - (void *(*)())(create ##classname), \ - (void (*)( void * ))(destroy ##classname) }; \ -} - -template<class T> -class Plugger -{ -public: - -public: - Plugger() : - hPlugin( new HashFunctionString(), 11 ), - hObj( new HashFunctionInt(), 11 ) - { - } - - virtual ~Plugger() - { - void *pos = hObj.getFirstItemPos(); - while( (pos = hObj.getNextItemPos( pos )) ) - { - T *pPlug = (T *)hObj.getItemID( pos ); - PluginReg *pReg = (PluginReg *)hObj.getItemData( pos ); - pReg->pInfo->destroyPlugin( pPlug ); - } - - std::list<PluginReg *>::iterator i; - for( i = lPlugin.begin(); i != lPlugin.end(); i++ ) - { - if( (*i)->bBuiltin == false ) - { - dlclose( (*i)->dlHandle ); - } - delete (*i); - } - } - - void registerBuiltinPlugin( PluginInfo *pInfo ) - { - PluginReg *pReg = new PluginReg; - pReg->bBuiltin = true; - pReg->pInfo = pInfo; - lPlugin.insert( lPlugin.end(), pReg ); - hPlugin.insert( pInfo->sID, pReg ); - } - - void registerExternalPlugin( const char *sFName, const char *sPluginName ) - { - PluginReg *pReg = (PluginReg *)hPlugin[sPluginName]; - if( pReg != NULL ) - { - hPlugin.del( sPluginName ); - dlclose( pReg->dlHandle ); - delete pReg; - pReg = NULL; - } - - pReg = new PluginReg; - - pReg->bBuiltin = false; - pReg->dlHandle = dlopen( sFName, RTLD_NOW ); - if( pReg->dlHandle == NULL ) - { - throw PluginException( 1, "Error on %s: %s", sFName, dlerror() ); - } - pReg->pInfo = (PluginInfo *)dlsym( pReg->dlHandle, sPluginName ); - if( pReg->pInfo == NULL ) - { - throw PluginException( 2, "Error on %s: %s", sFName, dlerror() ); - } - hPlugin.insert( pReg->pInfo->sID, pReg ); - lPlugin.insert( lPlugin.end(), pReg ); - } - - T *instantiate( const char *lpName ) - { - PluginReg *pReg = (PluginReg *)hPlugin[lpName]; - if( pReg == NULL ) - return NULL; - - T *p = (T *)pReg->pInfo->createPlugin(); - hObj.insert( p, pReg ); - //printf("pReg: %08X, pPlug: %08X\n", pReg, p ); - - return p; - } - - bool hasPlugin( const char *lpName ) - { - if( hPlugin[lpName] == NULL ) - return false; - return true; - } - - void destroy( T *pPlug ) - { - PluginReg *pReg = (PluginReg *)hObj[pPlug]; - //printf("pReg: %08X, pPlug: %08X\n", pReg, pPlug ); - if( pReg == NULL ) - return; - - pReg->pInfo->destroyPlugin( pPlug ); - - hObj.del( pPlug ); - } - - void unloadAll() - { - std::list<PluginReg *>::iterator i; - for( i = lPlugin.begin(); i != lPlugin.end(); i++ ) - { - if( (*i)->bBuiltin == false ) - { - dlclose( (*i)->dlHandle ); - } - delete (*i); - } - hPlugin.clear(); - } - -private: - std::list<PluginReg *> lPlugin; - HashTable hPlugin; - HashTable hObj; -}; - -#endif diff --git a/src/pqueue.cpp b/src/pqueue.cpp deleted file mode 100644 index 1f0b8b5..0000000 --- a/src/pqueue.cpp +++ /dev/null @@ -1,33 +0,0 @@ -#include "pqueue.h" - -PQueue::PQueue( int nNewNumQueues ) -{ - nNumQueues = nNewNumQueues; - aQueue = new Queue[nNumQueues]; -} - -PQueue::~PQueue() -{ - delete[] aQueue; -} - -void PQueue::enqueue( void *pData, int nQueueLevel ) -{ - if( nQueueLevel < 0 || nQueueLevel >= nNumQueues ) - return; - - aQueue[nQueueLevel].enqueue( pData ); -} - -void *PQueue::dequeue() -{ - for( int j = 0; j < nNumQueues; j++ ) - { - if( aQueue[j].isEmpty() == false ) - { - return aQueue[j].dequeue(); - } - } - - return NULL; -} diff --git a/src/pqueue.h b/src/pqueue.h deleted file mode 100644 index 8307d56..0000000 --- a/src/pqueue.h +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef PQUEUE_H -#define PQUEUE_H - -#include "queue.h" - -/** Priority queue. This is just like a queue, but something with a higher - * priority will always come off the queue before something with a lower - * priority, even if it's added after. Otherwise works just like a queue. - *@author Mike Buland - */ -class PQueue -{ -public: - /** Create a queue with any number of different priorities. - *@param nNewNumQueues The number of queues, the default is 3 - */ - PQueue( int nNewNumQueues=3 ); - - /** - * Cleanup all contained queues. - */ - virtual ~PQueue(); - - /** Add a new item to the queue at the specified priority. A lower - * number means a higher priority! - *@param pData A pointer to the data to add to the queue - *@param nQueueLevel The priority to set the new data to - */ - void enqueue( void *pData, int nQueueLevel ); - - /** Pull the next item off the queue, high priority first. - *@returns A pointer to the data that was next in the priority queue - */ - void *dequeue(); - -private: - /** - * The queues we use for real data storage. - */ - Queue *aQueue; - - /** - * The number of priorities or queus that we need. - */ - int nNumQueues; -}; - -#endif diff --git a/src/programchain.cpp b/src/programchain.cpp deleted file mode 100644 index 6120d58..0000000 --- a/src/programchain.cpp +++ /dev/null @@ -1,96 +0,0 @@ -#include <stdlib.h> -#include "programchain.h" - -ProgramChain::ProgramChain() : - xLog( MultiLog::getInstance() ) -{ - xLog.LineLog( MultiLog::LStatus, "Program Chain Initialized." ); -} - -ProgramChain::~ProgramChain() -{ -} - -bool ProgramChain::addLink( ProgramLink *pLink ) -{ - if( pLink->init() == false ) - { - emergencyShutdown(); - return false; - } - - lLink.append( pLink ); - - pLink->setChain( this ); - - return true; -} - -ProgramLink *ProgramChain::getLink( const char *lpName ) -{ - char a; - a = lpName[0]; - return NULL; -} - -ProgramLink *ProgramChain::getBaseLink() -{ - return NULL; -} - -bool ProgramChain::execChainOnce() -{ - int nLen = lLink.getSize(); - for( int j = 0; j < nLen; j++ ) - { - if( ((ProgramLink *)lLink[j])->timeSlice() == false ) - { - xLog.LineLog( MultiLog::LInfo, "Shutting down due to signal from link #%d", j ); - emergencyShutdown(); - return false; - } - } - - return true; -} - -bool ProgramChain::enterChainLoop() -{ - for(;;) - { - if( execChainOnce() == false ) - { - return false; - } - } - - return true; -} - -void ProgramChain::emergencyShutdown() -{ - int nLen = lLink.getSize(); - for( int j = 0; j < nLen; j++ ) - { - ((ProgramLink *)lLink[j])->deInit(); - delete (ProgramLink *)lLink[j]; - } - lLink.empty(); -} - -LinkMessage *ProgramChain::broadcastIRM( LinkMessage *pMsgOut, ProgramLink *pSender ) -{ - int nLen = lLink.getSize(); - for( int j = 0; j < nLen; j++ ) - { - LinkMessage *pMsg = ((ProgramLink *)lLink[j])->processIRM( pMsgOut ); - if( pMsg != NULL ) - { - delete pMsgOut; - return pMsg; - } - } - - delete pMsgOut; - return NULL; -} diff --git a/src/programchain.h b/src/programchain.h deleted file mode 100644 index 2bdfeee..0000000 --- a/src/programchain.h +++ /dev/null @@ -1,95 +0,0 @@ -#ifndef PROGRAMCHAIN_H -#define PROGRAMCHAIN_H - -#include "linkedlist.h" -#include "multilog.h" -#include "programlink.h" - -/** - * The Program Chain links together program "chunks" to more easily facilitate - * a generalized program loop with modular extensions. - *@author Mike Buland - */ -class ProgramChain -{ -public: - /** - * Construct an empty chain. - */ - ProgramChain(); - - /** - * Destroy your chain. - */ - virtual ~ProgramChain(); - - /** - * Adds a link to the end of the chain. - *@param pLink A pointer to the link to add to the chain. - *@returns True if adding the link was successful, otherwise false - *@author Mike Buland - */ - bool addLink( ProgramLink *pLink ); - - /** - * Gets a link by name. - *@param lpName The name of the link you're looking for. Every link has a - * name, apparently. - *@returns A pointer to the specified ProgramLink, or NULL if none were - * found matching your criteria. - *@author Mike Buland - */ - class ProgramLink *getLink( const char *lpName ); - - /** - * Gets the very first link in the chain. - *@returns A pointer to the first link in the chain. - *@author Mike Buland - */ - class ProgramLink *getBaseLink(); - - /** - * Runs through the chain once. Useful if you want to have more control - * over the operation of the chain. - *@returns true if every link returned true. If at least one link returns - * false, then returns false. - *@author Mike Buland - */ - bool execChainOnce(); - - /** - * Enters the master chain loop, looping over the entire chain and - * executing every link's TimeSlice routine in order, over and over, until - * a link returns a false value. - *@returns False, always. It returns true unless a link returned false, - * but loops until a link does return false. - *@author Mike Buland - **/ - bool enterChainLoop(); - - /** - * Broadcasts an Immediate Response Message to all active links, save the - * sender. Whatever link first responds with a non-null response message - * will have it's messages sent back to the broadcasting link as the returns - * of this function call. Therefore it is very important that all message - * processing code is handled in a fairly timely fasion. - *@param pMsgOut The message to broadcast in hopes of a response. - *@param pSender The message that sent out the message and doesn't want to - * receive it's own message. This should always just be "this". - *@returns The message that was returned by the first link to return a - * non-null response. If all messages return null responses then this also - * returns null. Please note that whoever calls this will be responsible - * for deleting the message returned by it, if non-null. - */ - class LinkMessage *broadcastIRM( LinkMessage *pMsgOut, ProgramLink *pSender ); - -private: - /** - * Shuts down all operation no matter what point in the operation we were. - */ - void emergencyShutdown(); - MultiLog &xLog; /**< A reference to the log. */ - LinkedList lLink; /**< The linked list that contains all of the links. */ -}; - -#endif diff --git a/src/programlink.cpp b/src/programlink.cpp deleted file mode 100644 index 21c6fe4..0000000 --- a/src/programlink.cpp +++ /dev/null @@ -1,54 +0,0 @@ -#include "programlink.h" -#include "programchain.h" - -ProgramLink::ProgramLink() -{ -} - -ProgramLink::~ProgramLink() -{ -} - -LinkMessage *ProgramLink::sendIRM( LinkMessage *pMsgOut ) -{ - return pChain->broadcastIRM( pMsgOut, this ); -} - -void ProgramLink::setChain( ProgramChain *pNewChain ) -{ - pChain = pNewChain; -} - -/* -void ProgramLink::postMessage( LinkMessage *pMsg, int nLvl ) -{ - if( nLvl == msgToChain ) - { - qMsgToChain.enqueue( pMsg ); - } - else if( nLvl == msgToLink ) - { - qMsgToLink.enqueue( pMsg ); - } - else - { - // ERROR! - } -} - -LinkMessage *ProgramLink::getMessage( int nLvl ) -{ - if( nLvl == msgToChain ) - { - return (LinkMessage *)qMsgToChain.dequeue(); - } - else if( nLvl == msgToLink ) - { - return (LinkMessage *)qMsgToLink.dequeue(); - } - else - { - // ERROR! - } -} -*/ diff --git a/src/programlink.h b/src/programlink.h deleted file mode 100644 index f93edcc..0000000 --- a/src/programlink.h +++ /dev/null @@ -1,99 +0,0 @@ -#ifndef PROGRAMLINK_H -#define PROGRAMLINK_H - -class ProgramLink; -#include "queue.h" -#include "linkmessage.h" -#include "programchain.h" - -/** - * Program Link is the base class for any object that will be a piece of the - * main program chain loop. - *@author Mike Buland - */ -class ProgramLink -{ -friend class ProgramChain; -public: - /** - * Construct a program link. - */ - ProgramLink(); - - /** - * Deconstruct. - */ - virtual ~ProgramLink(); - - /** - * Initialization code required for a link that wasn't performed in the - * constructor. - *@returns true if initialization was successful. A false value will halt - * the chain. - */ - virtual bool init()=0; - - /** - * DeInitialization code that should happen, but doesn't belong in the - * destructor. - *@returns true means everything worked, false means failure, but is - * meaningless. - */ - virtual bool deInit()=0; - - /** - * Executed once per link per chain pass. Contains the guts of the program. - *@returns true if everything went well. A false value will halt the chain. - */ - virtual bool timeSlice()=0; - - /** - * This must be handled in order to process Instant Response Messages. - * This function should return null on all messages that it doesn't - * understand how to handle, and construct new messages to return to sender - * in the cases where it does understand. - *@param pMsgIn The message that must be processed. - *@returns Either a new message in cases where a response is required, - * or null if nothing needs to be done by this link. - */ - virtual LinkMessage *processIRM( LinkMessage *pMsgIn ) = 0; - - /** - * Broadcast a LinkMessage to all other links in the system. Each other - * link will get a call of their processIRM function. If the message gets - * a response then you will regain control immediately, otherwise the system - * will give all other Links a chance to respond before returning NULL. - *@param pMsgOut The message to broadcast. - *@returns The message response, or NULL if no Link understood your message. - */ - LinkMessage *sendIRM( LinkMessage *pMsgOut ); - -private: - /** - * Set which chain we're assosiated with. This is how IRM messages make - * it out to the rest of the world. - *@param pNewChain A pointer to the containing program chain. - */ - void setChain( class ProgramChain *pNewChain ); - - /** - * The pointer to the containing chain. - */ - class ProgramChain *pChain; -/* - void postMessage( LinkMessage *pMsg, int nLvl ); - LinkMessage *getMessage( int nLvl ); - - enum - { - msgToChain, - msgToLink - }; - -private: - Queue qMsgToChain; - Queue qMsgToLink; -*/ -}; - -#endif diff --git a/src/protocol.cpp b/src/protocol.cpp deleted file mode 100644 index 78b3ee2..0000000 --- a/src/protocol.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include "protocol.h" - -Protocol::Protocol() -{ - pConnection = NULL; -} - -Protocol::~Protocol() -{ -} - -void Protocol::setConnection( Connection *pNewConnection ) -{ - pConnection = pNewConnection; -} - -Connection *Protocol::getConnection() -{ - return pConnection; -} diff --git a/src/protocol.h b/src/protocol.h deleted file mode 100644 index 09e1c98..0000000 --- a/src/protocol.h +++ /dev/null @@ -1,62 +0,0 @@ -#ifndef PROTOCOL_H -#define PROTOCOL_H - -#include "connection.h" - -/** This is the template for a class that handles specialized input and output - * to connections of different types with different protocols. - *@author Mike Buland - */ -class Protocol -{ -public: - /** Constructor */ - Protocol(); - /** Deconstructor */ - virtual ~Protocol(); - - /** - * Function is called every time there is new data on the line. This is - * called directly from the Connection class to process data. This is not - * called whever there is pending data on the input, but every time new data - * is added to the input buffer. - *@returns True if processing went alright, false if something went wrong, - * I suppose. In truth this value is thrown away right now. - *@todo Either make a return value of false mean something, or make these - * void. - */ - virtual bool onNewData()=0; - - /** - * Function is called when there is a new connection. This should only - * happen once per Protocol object, but gives each protocol object a - * chance to perform connection handshaking and initialization at a point - * where they know that they have a handle to an active Connection. - *@returns See onNewData - */ - virtual bool onNewConnection()=0; - - virtual void onNewClientConnection(){}; - - virtual void poll(){}; - - /** - * Sets the Protocol's Connection object. This is rather important, and - * handled usually by the ConnectionManager. - *@param pNewConnection The Connection object that this protocol will use to - * deal with the outside world. - */ - void setConnection( class Connection *pNewConnection ); - - /** - * Get a pointer to this object's Connection object, or NULL if one was - * never set. If used with the ConnectionManager that should never happen. - *@returns A pointer to the active Connection. - */ - Connection *getConnection(); - -private: - class Connection *pConnection; /**< The pointer to the Connection. */ -}; - -#endif diff --git a/src/protocoltelnet.cpp b/src/protocoltelnet.cpp deleted file mode 100644 index b169a51..0000000 --- a/src/protocoltelnet.cpp +++ /dev/null @@ -1,316 +0,0 @@ -#include "protocoltelnet.h" -#include <string.h> - -ProtocolTelnet::ProtocolTelnet() -{ - nTermType = termUnInited; - bEchoOn = true; -} - -ProtocolTelnet::~ProtocolTelnet() -{ -} - -bool ProtocolTelnet::onNewConnection() -{ - Connection *pCon = getConnection(); - - pCon->appendOutput( (char)IAC ); - pCon->appendOutput( (char)WILL ); - pCon->appendOutput( (char)SUPPRESSGA ); - - pCon->appendOutput( (char)IAC ); - pCon->appendOutput( (char)DO ); - pCon->appendOutput( (char)SUPPRESSGA ); - - pCon->appendOutput( (char)IAC ); - pCon->appendOutput( (char)DONT ); - pCon->appendOutput( (char)TERMTYPE ); - -// pCon->appendOutput( IAC ); -// pCon->appendOutput( SB ); -// pCon->appendOutput( TERMTYPE ); -// pCon->appendOutput( 1 ); -// pCon->appendOutput( IAC ); -// pCon->appendOutput( SE ); - - pCon->appendOutput( (char)IAC ); - pCon->appendOutput( (char)DONT ); - pCon->appendOutput( (char)ECHO ); - - pCon->appendOutput( (char)IAC ); - pCon->appendOutput( (char)WILL ); - pCon->appendOutput( (char)ECHO ); - -// 255(IAC),251(WILL),3 - return true; -} - -bool ProtocolTelnet::onNewData() -{ - Connection *pCon = getConnection(); - if( !pCon->hasInput() ) - { - return true; - } - - int nInSize = pCon->getInputAmnt(); - char *lpInStr = (char *)pCon->getInput(); - - // Here we interpret the basic commands and un-encapsulate them, so to - // speak. We'll allow this, even if the terminal is in raw mode, we - // just won't send anything in response... - for( int j = 0; j < nInSize; j++ ) - { - switch( (unsigned char)lpInStr[j] ) - { - case '\r': - fbEdited.appendData('\n'); - if( bEchoOn ) pCon->appendOutput("\n\r"); - break; - - case '\n': - break; - - case '\177': // backspace - if( fbEdited.getLength() > 0 ) - { - fbEdited.usedData( -1 ); // Delete one char from the end - if( bEchoOn ) pCon->appendOutput(ESC "[D"); // Move the cursor back one - if( bEchoOn ) pCon->appendOutput(ESC "[P"); // Delete one character - } - break; - - case '\x1B': // escape sequence - if( (unsigned char)lpInStr[j+1] == '[' ) - { - switch( (unsigned char)lpInStr[j+2] ) - { - case 'A': // Up - break; - - case 'B': // Down - break; - - case 'C': // Right - break; - - case 'D': // Left - break; - } - j+=2; - } - break; - - case 0: // NOP: No operation - break; - - case IAC: // IAC: Interpret as command - switch( lpInStr[j+1] ) - { - case SE: // SE: End of subnegotiation parameters. - break; - - case NOP: // NOP: No operation - break; - - 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. - break; - - case BRK: // BRK: Break. Indicates that the "break" or "attention" key was hit. - break; - - case IP: // IP: Suspend, interrupt or abort the process to which the NVT is connected. - break; - - case AO: // AO: Abort output. Allows the current process to run to completion but do not send its output to the user. - break; - - case AYT: // AYT: Are you there. Send back to the NVT some visible evidence that the AYT was received. - break; - - case EC: // EC: Erase character. The receiver should delete the last preceding undeleted character from the data stream. - break; - - case EL: // EL: Erase line. Delete characters from the data stream back to but not including the previous CRLF. - break; - - case GA: // GA: Go ahead. Used, under certain circumstances, to tell the other end that it can transmit. - break; - - case SB: // SB: Subnegotiation of the indicated option follows. - switch( lpInStr[j+2] ) - { - case TERMTYPE: - if( lpInStr[j+3] == 0 ) - { - for( int k = 0; j+4+k < nInSize; k++ ) - { - if( (unsigned char)lpInStr[j+4+k] == IAC && - (unsigned char)lpInStr[j+5+k] == SE ) - { - lpInStr[j+4+k] = 0; - //@TODO: Do something with the term type... - printf("Term type: %s\n", &lpInStr[j+4] ); - j += 5+k; - } - } - } - else - { - } - break; - - default: - //printf("unknown subnegotiation parameters! (%d)\n", lpInStr[j+2] ); - break; - } - break; - - case WILL: // WILL: Indicates the desire to begin performing - switch( lpInStr[j+2] ) - { - case SUPPRESSGA: - j += 2; -// pCon->usedInput( 3 ); - break; - - case TERMTYPE: - j += 2; -// pCon->usedInput( 3 ); - break; - - case ECHO: - j += 2; -// pCon->usedInput( 3 ); - break; - - case NAWS: - default: - pCon->appendOutput( (char)ESC[0] ); - pCon->appendOutput( (char)DONT ); - pCon->appendOutput( lpInStr[j+2] ); - //printf("unknown will command used! (%d)\n", lpInStr[j+2] ); - j += 2; - break; - } - break; - - case WONT: // WONT: Indicates the refusal to perform - switch( lpInStr[j+2] ) - { - case ECHO: - j += 2; -// pCon->usedInput( 3 ); - break; - - default: - //printf("unknown wont command used! (%d)\n", lpInStr[j+2] ); - j += 2; - break; - } - break; - - case DO: // DO: Indicates the request that the other party perform - switch( lpInStr[j+2] ) - { - case ECHO: - j += 2; - break; - - case SUPPRESSGA: - j += 2; - break; - - default: - pCon->appendOutput( (char)ESC[0] ); - pCon->appendOutput( (char)DONT ); - pCon->appendOutput( lpInStr[j+2] ); - //printf("unknown do command used! (%d)\n", lpInStr[j+2] ); - j += 2; - break; - } -// pCon->usedInput( 3 ); - break; - - case DONT: // DONT: Indicates the demand that the other party stop performing - switch( lpInStr[j+2] ) - { - case ECHO: - j += 2; -// pCon->usedInput( 3 ); - break; - - default: - printf("unknown dont command used! (%d)\n", lpInStr[j+2] ); - j += 2; - break; - } - break; - } - break; - - default: - fbEdited.appendData( lpInStr[j] ); - if( bEchoOn ) pCon->appendOutput( lpInStr[j] ); - break; - } - } - - pCon->usedInput( pCon->getInputAmnt() ); - - return true; -} - -char *ProtocolTelnet::getLine( bool bFullOnly ) -{ - int i = fbEdited.findChar('\n'); - - if( i < 0 ) - { - if( bFullOnly == false ) - { - i = fbEdited.getLength(); - } - else - { - return NULL; - } - } - - char *lpStr = new char[i+1]; - strncpy( lpStr, fbEdited.getData(), i ); - lpStr[i] = '\0'; - - fbEdited.usedData( i+1 ); - - return lpStr; -} - -char *ProtocolTelnet::peekLine( bool bFullOnly ) -{ - int i = fbEdited.findChar('\n'); - - if( i < 0 ) - { - if( bFullOnly == false ) - { - i = fbEdited.getLength(); - } - else - { - return NULL; - } - } - - char *lpStr = new char[i+1]; - strncpy( lpStr, fbEdited.getData(), i ); - lpStr[i] = '\0'; - - return lpStr; -} - -void ProtocolTelnet::setEcho( bool bEchoOn ) -{ - this->bEchoOn = bEchoOn; -} diff --git a/src/protocoltelnet.h b/src/protocoltelnet.h deleted file mode 100644 index a6d2e49..0000000 --- a/src/protocoltelnet.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef PROTOCOLTELNET_H -#define PROTOCOLTELNET_H - -#include "protocol.h" -#include "flexbuf.h" - -#define ESC "\x1B" /**< A telnet escape code. */ - -/** Handles all specialized protocol actions related to the telnet protocol. - * This includes setting modes, non-scrollable regions, and so on. - *@author Mike Buland - */ -class ProtocolTelnet : public Protocol -{ -public: - ProtocolTelnet(); - virtual ~ProtocolTelnet(); - - bool onNewData(); - bool onNewConnection(); - - char *getLine( bool bFullOnly = true ); - char *peekLine( bool bFullOnly = true ); - - void setEcho( bool bEchoOn = true ); - - enum - { - termUnInited, - termRaw, - termUnknown, - termVT220, - termXTerm - }; - - enum - { - SE = 240, // SE: End of subnegotiation parameters. - NOP = 241, // NOP: No operation - 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. - BRK = 243, // BRK: Break. Indicates that the "break" or "attention" key was hit. - IP = 244, // IP: Suspend, interrupt or abort the process to which the NVT is connected. - AO = 245, // AO: Abort output. Allows the current process to run to completion but do not send its output to the user. - AYT = 246, // AYT: Are you there. Send back to the NVT some visible evidence that the AYT was received. - EC = 247, // EC: Erase character. The receiver should delete the last preceding undeleted character from the data stream. - EL = 248, // EL: Erase line. Delete characters from the data stream back to but not including the previous CRLF. - GA = 249, // GA: Go ahead. Used, under certain circumstances, to tell the other end that it can transmit. - SB = 250, // SB: Subnegotiation of the indicated option follows. - WILL = 251, // WILL: Indicates the desire to begin performing, or confirmation that you are now performing, the indicated option. - WONT = 252, // WONT: Indicates the refusal to perform, or continue performing, the indicated option. - 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. - 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. - IAC = 255 // IAC: Interpret as command - }; - - enum - { - ECHO = 1, // Explain who'll echo - SUPPRESSGA = 3, // Suppress Go Ahead - TERMTYPE = 24, // Terminal Type - NAWS = 31, // Window size - TERMSPEED = 32, // Terminal Speed - LINEMODE = 34 // Linemode - }; - -private: - int nTermType; - - int nTermWidth; - int nTermHeight; - - FlexBuf fbEdited; - - bool bEchoOn; -}; - -#endif diff --git a/src/queue.cpp b/src/queue.cpp deleted file mode 100644 index 42999fe..0000000 --- a/src/queue.cpp +++ /dev/null @@ -1,26 +0,0 @@ -#include "queue.h" - -void Queue::enqueue( void *data ) -{ - lQueueData.append( data ); -} - -void *Queue::dequeue() -{ - void *dat = lQueueData[0]; - if( dat != NULL ) - { - lQueueData.deleteAt( 0 ); - } - return dat; -} - -bool Queue::isEmpty() -{ - return lQueueData.isEmpty(); -} - -void Queue::empty() -{ - lQueueData.empty(); -} diff --git a/src/queue.h b/src/queue.h deleted file mode 100644 index 692f5d8..0000000 --- a/src/queue.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef QUEUE_H -#define QUEUE_H -#include "linkedlist.h" - -/** - * An ultra-simple queue implementation. It just uses a linked list as it's - * container so we don't have to worry about anything! - *@author Mike Buland - */ -class Queue -{ -public: - /** - * Puts a new item at the end of the queue. - *@param data A new value to put at the end of the queue. - */ - void enqueue( void *data ); - - /** - * Gets the begining item of the queue off and returns it. - *@returns The value at the front of the queue. - */ - void *dequeue(); - - /** - * Checks if the queueu is empty. - *@returns True if the queueu is empty, and false if it has things in it. - */ - bool isEmpty(); - - /** - * Empty the queue. - */ - void empty(); - - /** - * Get a pointer to the internal list object. - *@returns A pointer to the internal list object. - */ - LinkedList *getList() { return &lQueueData; }; - -private: - LinkedList lQueueData; /**< Where all of the real data is stored. */ -}; -#endif diff --git a/src/ringlist.cpp b/src/ringlist.cpp deleted file mode 100644 index 9efbbc4..0000000 --- a/src/ringlist.cpp +++ /dev/null @@ -1,106 +0,0 @@ -// -// C++ Implementation: ringlist -// -// Description: -// -// -// Author: Mike Buland <eichlan@yf-soft.com>, (C) 2005 -// -// Copyright: See COPYING file that comes with this distribution -// -// -#include <stdlib.h> - -#include "ringlist.h" - -RingList::RingList( int nInitSize ) - : List() -{ - nFirstIndex = 0; - nRealLength = nInitSize; - nDataLength = 0; - apData = new void*[nInitSize]; - pPushBuf = NULL; -} - -RingList::~RingList() -{ - delete[] apData; -} - -void *RingList::getAt( int nIndex ) -{ - if( nIndex < 0 || nIndex >= nDataLength ) - { - return NULL; - } - - return apData[(nFirstIndex+nIndex)%nRealLength]; -} - -void RingList::append( void *pData ) -{ - int nIndex = (nFirstIndex+nDataLength)%nRealLength; - - pPushBuf = apData[nIndex]; - apData[nIndex] = pData; - - if( nDataLength == nRealLength ) - { - nFirstIndex = (nFirstIndex+1)%nRealLength; - } - else - { - nDataLength++; - // We really didn't need it this time... - pPushBuf = NULL; - } -} - -void RingList::insertBefore( void *pData, int nPos ) -{ - // Not implemented right now, don't even try it! -} - -int RingList::getSize() -{ - return nDataLength; -} - -bool RingList::isEmpty() -{ - return nDataLength==0; -} - -void RingList::deleteAt( int nIndex ) -{ - // Also not implemented yet -} - -void RingList::empty() -{ - nFirstIndex = 0; - nDataLength = 0; -} - -void RingList::setSize( int nNewSize ) -{ - if( apData ) - { - delete[] apData; - } - nFirstIndex = 0; - nRealLength = nNewSize; - nDataLength = 0; - apData = new void*[nNewSize]; -} - -void RingList::setAt( int nIndex, void *pData ) -{ - apData[(nIndex+nFirstIndex)%nRealLength] = pData; -} - -void *RingList::getPushBuf() -{ - return pPushBuf; -} diff --git a/src/ringlist.h b/src/ringlist.h deleted file mode 100644 index bc069f3..0000000 --- a/src/ringlist.h +++ /dev/null @@ -1,112 +0,0 @@ -#ifndef RINGLIST_H -#define RINGLIST_H - -#include "list.h" - -/** - * A RingList or Ring Buffer implementation. This is a list that never grows in - * size once it is created, but instead once it is full new items added to the - * RingList replace the oldest items and the zero-index is virtually shifted. - * Since no data is actually moved when zero-index moves, this is very - * efficient. - * <br> - * The items removed are not actually deleted by the RingList, so instead they - * are first moved into a temporary "Push Buffer" that can be accessed so that - * elements pushed off the edge of the RingList can be accessed for cleanup. - *@author Mike Buland - */ -class RingList : public List -{ -public: - /** - * Construct a RingList with a fixed initial size. This size never changes - * unless setSize is called later during normal operation. - *@param nInitSize The number of elements to allocate. - */ - RingList( int nInitSize ); - - /** - * Clean up the data structures, but not the contained elements. - */ - virtual ~RingList(); - - /** - * Get an element at the specified index. - *@param nIndex The index of the element to retreive. - *@returns A pointer to the requested element, or NULL if the element is - * not found or not initialized yet. - */ - void *getAt( int nIndex ); - - /** - * Append an element to the end of the list, overwriting the begining if - * necesarry. - *@param pData The pointer to append to the RingList. - */ - void append( void *pData ); - - /** - * Insert an element before another in the RingList, pushing all after it - * down the list. - *@param pData The data to insert. - *@param nPos The position that new the element should occupy in the list. - */ - void insertBefore( void *pData, int nPos = 0 ); - - /** - * Get the size of the array. - */ - int getSize(); - - /** - * Is the RingList empty? - *@returns True if it is empty, false otherwise. - */ - bool isEmpty(); - - /** - * Delete an element in the list, moving all later elements down one index. - *@param nIndex The index of the element to delete. - */ - void deleteAt( int nIndex ); - - /** - * Remove all elements from the RingList. - */ - void empty(); - - /** - * Set a new size for the RingList. Be careful with this one, if shrinking - * this may quietly create a memory leak. - *@param nNewSize The new size to set the RingList to. - *@todo Either fix this memory leak somehow or remove this function. - */ - void setSize( int nNewSize ); - - /** - * Set a specific element to a new value. - *@param nIndex The zero-based index to change the value of. - *@param pData The data to put at the location specified by nIndex. - */ - void setAt( int nIndex, void *pData ); - - /** - * Retrieve the contents of the push buffer. This is the data that is - * pushed off the end of the array if you append data and the list is full. - * This should be checked after every append operation to be sure there - * isn't anything that needs deleting. - *@returns The last value pushed off the RingList, or NULL if nothing was - * pushed off. - */ - void *getPushBuf(); - -private: - int nFirstIndex; /**< The index to be translated as zero. */ - int nRealLength; /**< The Amount of storage space available. */ - int nDataLength; /**< The number of elements filled in. */ - void **apData; /**< The actual data storage. */ - void *pPushBuf; /**< The push buffer. */ - -}; - -#endif diff --git a/src/sbuffer.cpp b/src/sbuffer.cpp deleted file mode 100644 index f84f8a3..0000000 --- a/src/sbuffer.cpp +++ /dev/null @@ -1,67 +0,0 @@ -#include <string.h> -#include "sbuffer.h" - -SBuffer::SBuffer() : - nPos( 0 ), - bOpen( true ) -{ -} - -SBuffer::~SBuffer() -{ -} - -void SBuffer::close() -{ - bOpen = false; - fbData.clearData(); -} - -size_t SBuffer::read( char *pBuf, size_t nBytes ) -{ - size_t nLeft = fbData.getLength() - nPos; - if( nBytes > nLeft ) - nBytes = nLeft; - - if( nLeft == 0 ) - return 0; - - memcpy( pBuf, fbData.getData()+nPos, nBytes ); - nPos += nBytes; - - return nBytes; -} - -size_t SBuffer::write( const char *pBuf, size_t nBytes ) -{ - fbData.appendData( pBuf, nBytes ); - nPos += nBytes; - - return nBytes; -} - -long SBuffer::tell() -{ - return nPos; -} - -void SBuffer::seek( long offset ) -{ - nPos += offset; -} - -void SBuffer::setPos( long pos ) -{ - nPos = pos; -} - -void SBuffer::setPosEnd( long pos ) -{ - nPos = fbData.getLength() - pos; -} - -bool SBuffer::isEOS() -{ - return nPos == fbData.getLength(); -} - diff --git a/src/sbuffer.h b/src/sbuffer.h deleted file mode 100644 index 65feb71..0000000 --- a/src/sbuffer.h +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef S_BUFFER_H -#define S_BUFFER_H - -#include <stdint.h> - -#include "stream.h" -#include "flexbuf.h" - -class SBuffer : public Stream -{ -public: - SBuffer(); - virtual ~SBuffer(); - - virtual void close(); - virtual size_t read( char *pBuf, size_t nBytes ); - - /** - *@todo Update this to write at nPos, not just append data. - */ - virtual size_t write( const char *pBuf, size_t nBytes ); - - virtual long tell(); - virtual void seek( long offset ); - virtual void setPos( long pos ); - virtual void setPosEnd( long pos ); - virtual bool isEOS(); - - FlexBuf &getBuffer() - { - return fbData; - } - -private: - long nPos; - bool bOpen; - FlexBuf fbData; -}; - -#endif diff --git a/src/serializable.cpp b/src/serializable.cpp deleted file mode 100644 index fd50943..0000000 --- a/src/serializable.cpp +++ /dev/null @@ -1,8 +0,0 @@ -#include "serializable.h" - -Serializable::Serializable() -{ -} -Serializable::~Serializable() -{ -} diff --git a/src/serializable.h b/src/serializable.h deleted file mode 100644 index 06def29..0000000 --- a/src/serializable.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef SERIALIZER_H -#define SERIALIZER_H - -//#include "serializer.h" - -/** - * The base class for any class you want to serialize. Simply include this as - * a base class, implement the purely virtual serialize function and you've got - * an easily serializable class. - */ -class Serializable -{ -public: - /** - * Does nothing, here for completeness. - */ - Serializable(); - - /** - * Here to ensure the deconstructor is virtual. - */ - virtual ~Serializable(); - - /** - * This is the main workhorse of the serialization system, just override and - * you've got a serializable class. A reference to the Serializer archive - * used is passed in as your only parameter, query it to discover if you are - * loading or saving. - * @param ar A reference to the Serializer object to use. - */ - virtual void serialize( class Serializer &ar )=0; -}; - -#endif diff --git a/src/serializer.cpp b/src/serializer.cpp deleted file mode 100644 index 636224e..0000000 --- a/src/serializer.cpp +++ /dev/null @@ -1,338 +0,0 @@ -#include "serializer.h" -#include "serializable.h" -#include <list> - -Serializer::Serializer(bool bLoading): - bLoading(bLoading) -{ -} -Serializer::~Serializer() -{ -} - -bool Serializer::isLoading() -{ - return bLoading; -} -Serializer &Serializer::operator<<(bool p) -{ - write( &p, sizeof(p) ); - return *this; -} -Serializer &Serializer::operator<<(int8_t p) -{ - write( &p, sizeof(p) ); - return *this; -} -Serializer &Serializer::operator<<(int16_t p) -{ - write( &p, sizeof(p) ); - return *this; -} -Serializer &Serializer::operator<<(int32_t p) -{ - write( &p, sizeof(p) ); - return *this; -} -Serializer &Serializer::operator<<(int64_t p) -{ - write( &p, sizeof(p) ); - return *this; -} -Serializer &Serializer::operator<<(uint8_t p) -{ - write( &p, sizeof(p) ); - return *this; -} -Serializer &Serializer::operator<<(uint16_t p) -{ - write( &p, sizeof(p) ); - return *this; -} -Serializer &Serializer::operator<<(uint32_t p) -{ - write( &p, sizeof(p) ); - return *this; -} -Serializer &Serializer::operator<<(uint64_t p) -{ - write( &p, sizeof(p) ); - return *this; -} -Serializer &Serializer::operator<<(long p) -{ - write( &p, sizeof(p) ); - return *this; -} -Serializer &Serializer::operator<<(float p) -{ - write( &p, sizeof(p) ); - return *this; -} -Serializer &Serializer::operator<<(double p) -{ - write( &p, sizeof(p) ); - return *this; -} -Serializer &Serializer::operator<<(long double p) -{ - write( &p, sizeof(p) ); - return *this; -} - -Serializer &Serializer::operator>>(bool &p) -{ - read( &p, sizeof(p) ); - return *this; -} -Serializer &Serializer::operator>>(int8_t &p) -{ - read( &p, sizeof(p) ); - return *this; -} -Serializer &Serializer::operator>>(int16_t &p) -{ - read( &p, sizeof(p) ); - return *this; -} -Serializer &Serializer::operator>>(int32_t &p) -{ - read( &p, sizeof(p) ); - return *this; -} -Serializer &Serializer::operator>>(int64_t &p) -{ - read( &p, sizeof(p) ); - return *this; -} -Serializer &Serializer::operator>>(uint8_t &p) -{ - read( &p, sizeof(p) ); - return *this; -} -Serializer &Serializer::operator>>(uint16_t &p) -{ - read( &p, sizeof(p) ); - return *this; -} -Serializer &Serializer::operator>>(uint32_t &p) -{ - read( &p, sizeof(p) ); - return *this; -} -Serializer &Serializer::operator>>(uint64_t &p) -{ - read( &p, sizeof(p) ); - return *this; -} -Serializer &Serializer::operator>>(long &p) -{ - read( &p, sizeof(p) ); - return *this; -} -Serializer &Serializer::operator>>(float &p) -{ - read( &p, sizeof(p) ); - return *this; -} -Serializer &Serializer::operator>>(double &p) -{ - read( &p, sizeof(p) ); - return *this; -} -Serializer &Serializer::operator>>(long double &p) -{ - read( &p, sizeof(p) ); - return *this; -} - -Serializer &Serializer::operator&&(bool &p) -{ - if (bLoading) - { - return *this >> p; - } - else - { - return *this << p; - } -} - -Serializer &Serializer::operator&&(int8_t &p) -{ - if (bLoading) - { - return *this >> p; - } - else - { - return *this << p; - } -} - -Serializer &Serializer::operator&&(int16_t &p) -{ - if (bLoading) - { - return *this >> p; - } - else - { - return *this << p; - } -} - -Serializer &Serializer::operator&&(int32_t &p) -{ - if (bLoading) - { - return *this >> p; - } - else - { - return *this << p; - } -} - -Serializer &Serializer::operator&&(int64_t &p) -{ - if (bLoading) - { - return *this >> p; - } - else - { - return *this << p; - } -} - -Serializer &Serializer::operator&&(uint8_t &p) -{ - if (bLoading) - { - return *this >> p; - } - else - { - return *this << p; - } -} - -Serializer &Serializer::operator&&(uint16_t &p) -{ - if (bLoading) - { - return *this >> p; - } - else - { - return *this << p; - } -} - -Serializer &Serializer::operator&&(uint32_t &p) -{ - if (bLoading) - { - return *this >> p; - } - else - { - return *this << p; - } -} - -Serializer &Serializer::operator&&(uint64_t &p) -{ - if (bLoading) - { - return *this >> p; - } - else - { - return *this << p; - } -} - -Serializer &Serializer::operator&&(float &p) -{ - if (bLoading) - { - return *this >> p; - } - else - { - return *this << p; - } -} - -Serializer &Serializer::operator&&(double &p) -{ - if (bLoading) - { - return *this >> p; - } - else - { - return *this << p; - } -} - -Serializer &Serializer::operator&&(long double &p) -{ - if (bLoading) - { - return *this >> p; - } - else - { - return *this << p; - } -} - - -Serializer &operator<<(Serializer &s, Serializable &p) -{ - p.serialize( s ); - return s; -} - -Serializer &operator>>(Serializer &s, Serializable &p) -{ - p.serialize( s ); - return s; -} - -Serializer &operator&&(Serializer &s, Serializable &p) -{ - if (s.isLoading()) - { - return s >> p; - } - else - { - return s << p; - } -} - -Serializer &operator<<( Serializer &ar, std::string &s ) -{ - ar << (uint32_t)s.length(); - ar.write( s.c_str(), s.length() ); - - return ar; -} - -Serializer &operator>>( Serializer &ar, std::string &s ) -{ - uint32_t l; - ar >> l; - char *tmp = new char[l+1]; - tmp[l] = '\0'; - ar.read( tmp, l ); - s = tmp; - delete[] tmp; - - return ar; -} - diff --git a/src/serializer.h b/src/serializer.h deleted file mode 100644 index 3af489c..0000000 --- a/src/serializer.h +++ /dev/null @@ -1,80 +0,0 @@ -#ifndef SERIALIZABLE_H -#define SERIALIZABLE_H - -#include <stdint.h> -#include <string> -#include <list> -//#include "serializable.h" - -class Serializer -{ -private: - bool bLoading; -public: - bool isLoading(); - - enum - { - load = true, - save = false - }; - - Serializer(bool bLoading); - virtual ~Serializer(); - virtual void close()=0; - - virtual void write(const void *, int32_t)=0; - virtual void read(void *, int32_t)=0; - - virtual Serializer &operator<<(bool); - virtual Serializer &operator<<(int8_t); - virtual Serializer &operator<<(int16_t); - virtual Serializer &operator<<(int32_t); - virtual Serializer &operator<<(int64_t); - virtual Serializer &operator<<(uint8_t); - virtual Serializer &operator<<(uint16_t); - virtual Serializer &operator<<(uint32_t); - virtual Serializer &operator<<(uint64_t); - virtual Serializer &operator<<(long); - virtual Serializer &operator<<(float); - virtual Serializer &operator<<(double); - virtual Serializer &operator<<(long double); - - virtual Serializer &operator>>(bool &); - virtual Serializer &operator>>(int8_t &); - virtual Serializer &operator>>(int16_t &); - virtual Serializer &operator>>(int32_t &); - virtual Serializer &operator>>(int64_t &); - virtual Serializer &operator>>(uint8_t &); - virtual Serializer &operator>>(uint16_t &); - virtual Serializer &operator>>(uint32_t &); - virtual Serializer &operator>>(uint64_t &); - virtual Serializer &operator>>(long &); - virtual Serializer &operator>>(float &); - virtual Serializer &operator>>(double &); - virtual Serializer &operator>>(long double &); - - virtual Serializer &operator&&(bool &); - virtual Serializer &operator&&(int8_t &); - virtual Serializer &operator&&(int16_t &); - virtual Serializer &operator&&(int32_t &); - virtual Serializer &operator&&(int64_t &); - virtual Serializer &operator&&(uint8_t &); - virtual Serializer &operator&&(uint16_t &); - virtual Serializer &operator&&(uint32_t &); - virtual Serializer &operator&&(uint64_t &); - virtual Serializer &operator&&(float &); - virtual Serializer &operator&&(double &); - virtual Serializer &operator&&(long double &); - - //virtual Serializer &operator&(Serializable &); -}; - -Serializer &operator<<(Serializer &, class Serializable &); -Serializer &operator>>(Serializer &, class Serializable &); -Serializer &operator&&(Serializer &s, class Serializable &p); - -Serializer &operator<<(Serializer &, std::string &); -Serializer &operator>>(Serializer &, std::string &); - -#endif diff --git a/src/serializerbinary.cpp b/src/serializerbinary.cpp deleted file mode 100644 index ea7ed93..0000000 --- a/src/serializerbinary.cpp +++ /dev/null @@ -1,63 +0,0 @@ -#include "serializerbinary.h" -#include "serializable.h" -#include "exceptions.h" - -SerializerBinary::SerializerBinary(FILE *fhFile, bool bLoading): - Serializer(bLoading), - fhFile(fhFile), - bCloseFile(false) -{ -} - -SerializerBinary::SerializerBinary(const char *sFileName, bool bLoading): - Serializer(bLoading), - bCloseFile(true) -{ - if (bLoading) - { - fhFile = fopen(sFileName, "rb"); - if( fhFile == NULL ) - throw FileException("Unable to open file: %s", sFileName ); - } - else - { - fhFile = fopen(sFileName, "wb"); - if( fhFile == NULL ) - throw FileException("Unable to open file: %s", sFileName ); - } -} - -SerializerBinary::~SerializerBinary() -{ - close(); -} - -void SerializerBinary::close() -{ - if (fhFile != NULL && bCloseFile ) - { - fclose(fhFile); - fhFile = NULL; - } -} - -void SerializerBinary::write(const void * pData, int32_t nSize) -{ - if( nSize == 0 ) - return; - - fwrite(pData, nSize, 1, fhFile); -} - -void SerializerBinary::read(void * pData, int32_t nSize) -{ - if( nSize == 0 ) - return; - - uint32_t nRead = fread(pData, nSize, 1, fhFile); - if( nRead < 1 ) - { - throw FileException( excodeEOF, "End of file read"); - } -} - diff --git a/src/serializerbinary.h b/src/serializerbinary.h deleted file mode 100644 index 8510fcd..0000000 --- a/src/serializerbinary.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef SERIALIZER_BINARY_H -#define SERIALIZER_BINARY_H - -#include "serializer.h" -#include <stdio.h> - -class SerializerBinary : public Serializer -{ -public: - SerializerBinary(FILE *fhFile, bool bLoading); - SerializerBinary(const char *sFileName, bool bLoading); - virtual ~SerializerBinary(); - - virtual void close(); - - virtual void write(const void *, int32_t); - virtual void read(void *, int32_t); - -private: - FILE *fhFile; - bool bCloseFile; -}; - -#endif diff --git a/src/serializerbzip2.cpp b/src/serializerbzip2.cpp deleted file mode 100644 index bafabc8..0000000 --- a/src/serializerbzip2.cpp +++ /dev/null @@ -1,88 +0,0 @@ -#include "serializerbzip2.h" -#include "serializable.h" - -#include <bzlib.h> - -SerializerBZip2::SerializerBZip2(FILE *fhFile, bool bLoading): - Serializer(bLoading), - fhFile(fhFile), - bCloseFile(false) -{ - if( bLoading ) - { - bzFile = BZ2_bzReadOpen( &bzerror, fhFile, 0, 0, NULL, 0 ); - checkBZError(); - } - else - { - bzFile = BZ2_bzWriteOpen( &bzerror, fhFile, 9, 0, 0 ); - checkBZError(); - } -} - -SerializerBZip2::SerializerBZip2(char *sFileName, bool bLoading): - Serializer(bLoading), - bCloseFile(true) -{ - if (bLoading) - { - fhFile = fopen(sFileName, "rb"); - bzFile = BZ2_bzReadOpen( &bzerror, fhFile, 0, 0, NULL, 0 ); - checkBZError(); - } - else - { - fhFile = fopen(sFileName, "wb"); - bzFile = BZ2_bzWriteOpen( &bzerror, fhFile, 9, 0, 0 ); - checkBZError(); - } -} - -SerializerBZip2::~SerializerBZip2() -{ - close(); -} - -void SerializerBZip2::checkBZError() -{ -} - -void SerializerBZip2::close() -{ - if( bzFile != NULL ) - { - if( isLoading() ) - { - void *unused; - int nUnused; - BZ2_bzReadGetUnused( &bzerror, bzFile, &unused, &nUnused ); - BZ2_bzReadClose( &bzerror, bzFile ); - if( nUnused ) - fseek( fhFile, -nUnused, SEEK_CUR ); - } - else - { - BZ2_bzWriteClose( &bzerror, bzFile, 0, 0, 0 ); - } - checkBZError(); - bzFile = NULL; - } - if( fhFile != NULL && bCloseFile ) - { - fclose(fhFile); - fhFile = NULL; - } -} - -void SerializerBZip2::write(const void * pData, int32_t nSize) -{ - BZ2_bzWrite( &bzerror, bzFile, (void *)pData, nSize ); - checkBZError(); -} - -void SerializerBZip2::read(void * pData, int32_t nSize) -{ - BZ2_bzRead( &bzerror, bzFile, pData, nSize ); - checkBZError(); -} - diff --git a/src/serializerbzip2.h b/src/serializerbzip2.h deleted file mode 100644 index 4aeb22e..0000000 --- a/src/serializerbzip2.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef SERIALIZER_BINARY_H -#define SERIALIZER_BINARY_H - -#include "serializer.h" -#include <stdio.h> - -class SerializerBZip2 : public Serializer -{ -public: - SerializerBZip2(FILE *fhFile, bool bLoading); - SerializerBZip2(char *sFileName, bool bLoading); - virtual ~SerializerBZip2(); - - virtual void close(); - - virtual void write(const void *, int32_t); - virtual void read(void *, int32_t); - -private: - void checkBZError(); - FILE *fhFile; - void *bzFile; - bool bCloseFile; - int bzerror; -}; - -#endif diff --git a/src/serializerconnection.cpp b/src/serializerconnection.cpp deleted file mode 100644 index 2934c8b..0000000 --- a/src/serializerconnection.cpp +++ /dev/null @@ -1,15 +0,0 @@ -#include "serializerconnection.h" - -SerializerConnection::SerializerConnection( - Connection *pCon, bool bIO, int nTimeSec, int nTimeUSec ) : - Serializer( bIO ), - pCon( pCon ), - nTimeSec( nTimeSec ), - nTimeUSec( nTimeUSec ) -{ -} - -SerializerConnection::~SerializerConnection() -{ -} - diff --git a/src/serializerconnection.h b/src/serializerconnection.h deleted file mode 100644 index e8d85c6..0000000 --- a/src/serializerconnection.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef SERIALIZER_CONNECTION_H -#define SERIALIZER_CONNECTION_H - -#include <stdint.h> - -#include "serializer.h" -#include "connection.h" - -/** - * - */ -class SerializerConnection : public Serializer -{ -public: - SerializerConnection( Connection *pCon, bool bIO, int nTimeSec, int nTimeUSec ); - virtual ~SerializerConnection(); - -private: - Connection *pCon; - int nTimeSec; - int nTimeUSec; -}; - -#endif diff --git a/src/serializertext.cpp b/src/serializertext.cpp deleted file mode 100644 index 9cf4394..0000000 --- a/src/serializertext.cpp +++ /dev/null @@ -1,170 +0,0 @@ -#include "serializertext.h" - -SerializerText::SerializerText(FILE *fhFile, bool bLoading): - Serializer(bLoading), - fhFile(fhFile), - bCloseFile(false) -{ -} - -SerializerText::SerializerText(const char *sFileName, bool bLoading): - Serializer(bLoading), - bCloseFile(true) -{ - if (bLoading) - { - fhFile = fopen(sFileName, "rt"); - } - else - { - fhFile = fopen(sFileName, "wt"); - } -} - -SerializerText::~SerializerText() -{ - close(); -} - -void SerializerText::close() -{ - if (fhFile != NULL) - { - fclose(fhFile); - fhFile = NULL; - } -} - -void SerializerText::write(const void * pData, int32_t nSize) -{ - fwrite(pData, nSize, 1, fhFile); - fprintf(fhFile, "\n"); -} - -void SerializerText::read(void * pData, int32_t nSize) -{ - fread(pData, nSize, 1, fhFile); - fgetc(fhFile); -} - -Serializer &SerializerText::operator<<(bool p) -{ - fprintf(fhFile, "%hhd\n", p); - return *this; -} -Serializer &SerializerText::operator<<(int8_t p) -{ - fprintf(fhFile, "%hhd\n", p); - return *this; -} -Serializer &SerializerText::operator<<(int16_t p) -{ - fprintf(fhFile, "%hd\n", p); - return *this; -} -Serializer &SerializerText::operator<<(int32_t p) -{ - fprintf(fhFile, "%d\n", p); - return *this; -} -Serializer &SerializerText::operator<<(int64_t p) -{ - fprintf(fhFile, "%lld\n", p); - return *this; -} -Serializer &SerializerText::operator<<(uint8_t p) -{ - fprintf(fhFile, "%hhu\n", p); - return *this; -} -Serializer &SerializerText::operator<<(uint16_t p) -{ - fprintf(fhFile, "%hu\n", p); - return *this; -} -Serializer &SerializerText::operator<<(uint32_t p) -{ - fprintf(fhFile, "%u\n", p); - return *this; -} -Serializer &SerializerText::operator<<(uint64_t p) -{ - fprintf(fhFile, "%llu\n", p); - return *this; -} -Serializer &SerializerText::operator<<(float p) -{ - fprintf(fhFile, "%f\n", p); - return *this; -} -Serializer &SerializerText::operator<<(double p) -{ - fprintf(fhFile, "%f\n", p); - return *this; -} -Serializer &SerializerText::operator<<(long double p) -{ - fprintf(fhFile, "%Lf\n", p); - return *this; -} - -Serializer &SerializerText::operator>>(bool &p) -{ - fscanf(fhFile, "%hhd\n", ((signed char *)&p)); - return *this; -} -Serializer &SerializerText::operator>>(int8_t &p) -{ - fscanf(fhFile, "%hhd\n", &p); - return *this; -} -Serializer &SerializerText::operator>>(int16_t &p) -{ - fscanf(fhFile, "%hd\n", &p); - return *this; -} -Serializer &SerializerText::operator>>(int32_t &p) -{ - fscanf(fhFile, "%d\n", &p); - return *this; -} -Serializer &SerializerText::operator>>(int64_t &p) -{ - fscanf(fhFile, "%lld\n", &p); - return *this; -} -Serializer &SerializerText::operator>>(uint8_t &p) -{ - fscanf(fhFile, "%hhu\n", &p); - return *this; -} -Serializer &SerializerText::operator>>(uint16_t &p) -{ - fscanf(fhFile, "%hu\n", &p); - return *this; -} -Serializer &SerializerText::operator>>(uint32_t &p) -{ - fscanf(fhFile, "%u\n", &p); - return *this; -} -Serializer &SerializerText::operator>>(uint64_t &p) -{ - fscanf(fhFile, "%llu\n", &p); - return *this; -} -Serializer &SerializerText::operator>>(float &p) -{ - fscanf(fhFile, "%f\n", &p); - return *this; -} -Serializer &SerializerText::operator>>(double &p) -{ - fscanf(fhFile, "%lf\n", &p); - return *this; -} -Serializer &SerializerText::operator>>(long double &p) -{ - fscanf(fhFile, "%Lf\n", &p); - return *this; -} diff --git a/src/serializertext.h b/src/serializertext.h deleted file mode 100644 index 01b7f7b..0000000 --- a/src/serializertext.h +++ /dev/null @@ -1,49 +0,0 @@ -#ifndef SERIALIZER_TEXT_H -#define SERIALIZER_TEXT_H - -#include "serializer.h" -#include <stdio.h> - -class SerializerText : public Serializer -{ -public: - SerializerText(FILE *fhFile, bool bLoading); - SerializerText(const char *sFileName, bool bLoading); - virtual ~SerializerText(); - - virtual void close(); - - virtual void write(const void *, int32_t); - virtual void read(void *, int32_t); - - virtual Serializer &operator<<(bool); - virtual Serializer &operator<<(int8_t); - virtual Serializer &operator<<(int16_t); - virtual Serializer &operator<<(int32_t); - virtual Serializer &operator<<(int64_t); - virtual Serializer &operator<<(uint8_t); - virtual Serializer &operator<<(uint16_t); - virtual Serializer &operator<<(uint32_t); - virtual Serializer &operator<<(uint64_t); - virtual Serializer &operator<<(float); - virtual Serializer &operator<<(double); - virtual Serializer &operator<<(long double); - - virtual Serializer &operator>>(bool &); - virtual Serializer &operator>>(int8_t &); - virtual Serializer &operator>>(int16_t &); - virtual Serializer &operator>>(int32_t &); - virtual Serializer &operator>>(int64_t &); - virtual Serializer &operator>>(uint8_t &); - virtual Serializer &operator>>(uint16_t &); - virtual Serializer &operator>>(uint32_t &); - virtual Serializer &operator>>(uint64_t &); - virtual Serializer &operator>>(float &); - virtual Serializer &operator>>(double &); - virtual Serializer &operator>>(long double &); -private: - FILE *fhFile; - bool bCloseFile; -}; - -#endif diff --git a/src/sfile.cpp b/src/sfile.cpp deleted file mode 100644 index f1de03c..0000000 --- a/src/sfile.cpp +++ /dev/null @@ -1,74 +0,0 @@ -#include "sfile.h" -#include "exceptions.h" - -SFile::SFile( const char *sName, const char *sFlags ) -{ - fh = fopen( sName, sFlags ); -} - -SFile::~SFile() -{ -} - -void SFile::close() -{ - if( fh ) - { - fclose( fh ); - fh = NULL; - } -} - -size_t SFile::read( char *pBuf, size_t nBytes ) -{ - if( !fh ) - throw FileException("File not open."); - - return fread( pBuf, 1, nBytes, fh ); -} - -size_t SFile::write( const char *pBuf, size_t nBytes ) -{ - if( !fh ) - throw FileException("File not open."); - - return fwrite( pBuf, 1, nBytes, fh ); -} - -long SFile::tell() -{ - if( !fh ) - throw FileException("File not open."); - - return ftell( fh ); -} - -void SFile::seek( long offset ) -{ - if( !fh ) - throw FileException("File not open."); - - fseek( fh, offset, SEEK_CUR ); -} - -void SFile::setPos( long pos ) -{ - if( !fh ) - throw FileException("File not open."); - - fseek( fh, pos, SEEK_SET ); -} - -void SFile::setPosEnd( long pos ) -{ - if( !fh ) - throw FileException("File not open."); - - fseek( fh, pos, SEEK_END ); -} - -bool SFile::isEOS() -{ - return feof( fh ); -} - diff --git a/src/sfile.h b/src/sfile.h deleted file mode 100644 index b51e5bc..0000000 --- a/src/sfile.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef SFILE_H -#define SFILE_H - -#include <stdint.h> - -#include "stream.h" - -class SFile : public Stream -{ -public: - SFile( const char *sName, const char *sFlags ); - virtual ~SFile(); - - virtual void close(); - virtual size_t read( char *pBuf, size_t nBytes ); - virtual size_t write( const char *pBuf, size_t nBytes ); - - virtual long tell(); - virtual void seek( long offset ); - virtual void setPos( long pos ); - virtual void setPosEnd( long pos ); - virtual bool isEOS(); - -private: - FILE *fh; - -}; - -#endif diff --git a/src/sha1.cpp b/src/sha1.cpp deleted file mode 100644 index 8270c3b..0000000 --- a/src/sha1.cpp +++ /dev/null @@ -1,161 +0,0 @@ -#include <stdio.h> -#include <string.h> -#include <stdlib.h> - -#include "sha1.h" - -Sha1::Sha1() : - H0( 0x67452301 ), - H1( 0xefcdab89 ), - H2( 0x98badcfe ), - H3( 0x10325476 ), - H4( 0xc3d2e1f0 ), - unprocessedBytes( 0 ), - size( 0 ) -{ -} - -Sha1::~Sha1() -{ -} - -void Sha1::process() -{ - int t; - uint32_t a, b, c, d, e, K, f, W[80]; - - // starting values - a = H0; - b = H1; - c = H2; - d = H3; - e = H4; - - // copy and expand the message block - for( t = 0; t < 16; t++ ) W[t] = (bytes[t*4] << 24) - +(bytes[t*4 + 1] << 16) - +(bytes[t*4 + 2] << 8) - + bytes[t*4 + 3]; - for(; t< 80; t++ ) W[t] = lrot( W[t-3]^W[t-8]^W[t-14]^W[t-16], 1 ); - - /* main loop */ - uint32_t temp; - for( t = 0; t < 80; t++ ) - { - if( t < 20 ) { - K = 0x5a827999; - f = (b & c) | ((~b) & d); - } else if( t < 40 ) { - K = 0x6ed9eba1; - f = b ^ c ^ d; - } else if( t < 60 ) { - K = 0x8f1bbcdc; - f = (b & c) | (b & d) | (c & d); - } else { - K = 0xca62c1d6; - f = b ^ c ^ d; - } - temp = lrot(a,5) + f + e + W[t] + K; - e = d; - d = c; - c = lrot(b,30); - b = a; - a = temp; - //printf( "t=%d %08x %08x %08x %08x %08x\n",t,a,b,c,d,e ); - } - - /* add variables */ - H0 += a; - H1 += b; - H2 += c; - H3 += d; - H4 += e; - - //printf( "Current: %08x %08x %08x %08x %08x\n",H0,H1,H2,H3,H4 ); - /* all bytes have been processed */ - unprocessedBytes = 0; -} - -void Sha1::update( const char* data, int num ) -{ - // add these bytes to the running total - size += num; - - // repeat until all data is processed - while( num > 0 ) - { - // number of bytes required to complete block - int needed = 64 - unprocessedBytes; - - // number of bytes to copy (use smaller of two) - int toCopy = (num < needed) ? num : needed; - - // Copy the bytes - memcpy( bytes + unprocessedBytes, data, toCopy ); - - // Bytes have been copied - num -= toCopy; - data += toCopy; - unprocessedBytes += toCopy; - - // there is a full block - if( unprocessedBytes == 64 ) process(); - } -} - -unsigned char* Sha1::getDigest() -{ - // save the message size - uint32_t totalBitsL = size << 3; - uint32_t totalBitsH = size >> 29; - - // add 0x80 to the message - update( "\x80", 1 ); - - unsigned char footer[64] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - - // block has no room for 8-byte filesize, so finish it - if( unprocessedBytes > 56 ) - update( (char*)footer, 64 - unprocessedBytes); - - // how many zeros do we need - int neededZeros = 56 - unprocessedBytes; - - // store file size (in bits) in big-endian format - toBigEndian( totalBitsH, footer + neededZeros ); - toBigEndian( totalBitsL, footer + neededZeros + 4 ); - - // finish the final block - update( (char*)footer, neededZeros + 8 ); - - // allocate memory for the digest bytes - unsigned char* digest = new unsigned char[20]; - - // copy the digest bytes - toBigEndian( H0, digest ); - toBigEndian( H1, digest + 4 ); - toBigEndian( H2, digest + 8 ); - toBigEndian( H3, digest + 12 ); - toBigEndian( H4, digest + 16 ); - - // return the digest - return digest; -} - -uint32_t Sha1::lrot( uint32_t x, int bits ) -{ - return (x<<bits) | (x>>(32 - bits)); -}; - -void Sha1::toBigEndian( uint32_t num, unsigned char* byte ) -{ - byte[0] = (unsigned char)(num>>24); - byte[1] = (unsigned char)(num>>16); - byte[2] = (unsigned char)(num>>8); - byte[3] = (unsigned char)num; -} - diff --git a/src/sha1.h b/src/sha1.h deleted file mode 100644 index ab6081d..0000000 --- a/src/sha1.h +++ /dev/null @@ -1,42 +0,0 @@ -/* sha1.h - -Copyright (c) 2005 Michael D. Leonhard - -http://tamale.net/ - -This file is licensed under the terms described in the -accompanying LICENSE file. -*/ - -#ifndef SHA1_H -#define SHA1_H - -#include <stdint.h> - -/** - * Calculates SHA-1 sums. This is based strongly on code from Michael D. - * Leonhard who released his code under the terms of the MIT license, thank you! - */ -class Sha1 -{ -public: - Sha1(); - ~Sha1(); - - void update( const char* data, int num ); - unsigned char* getDigest(); - - // utility methods - static uint32_t lrot( uint32_t x, int bits ); - static void toBigEndian( uint32_t in, unsigned char* out ); - -private: - // fields - uint32_t H0, H1, H2, H3, H4; - unsigned char bytes[64]; - int unprocessedBytes; - uint32_t size; - void process(); -}; - -#endif diff --git a/src/singleton.h b/src/singleton.h deleted file mode 100644 index 47adbd5..0000000 --- a/src/singleton.h +++ /dev/null @@ -1,59 +0,0 @@ -#ifndef SINGLETON_H -#define SINGLETON_H - -#include <stdio.h> - -/** - * Provides singleton functionality in a modular sort of way. Make this the - * base class of any other class and you immediately gain singleton - * functionality. Be sure to make your constructor and various functions use - * intellegent scoping. Cleanup and instantiation are performed automatically - * for you at first use and program exit. There are two things that you must - * do when using this template, first is to inherit from it with the name of - * your class filling in for T and then make this class a friend of your class. - *@code - * // Making the Single Singleton: - * class Single : public Singleton<Single> - * { - * friend class Singleton<Single>; - * protected: - * Single(); - * ... - * }; - @endcode - * You can still add public functions and variables to your new Singleton child - * class, but your constructor should be protected (hence the need for the - * friend decleration). - *@author Mike Buland - */ -template <class T> -class Singleton -{ -protected: - /** - * Private constructor. This constructor is empty but has a body so that - * you can make your own override of it. Be sure that you're override is - * also protected. - */ - Singleton() {}; - -private: - /** - * Copy constructor, defined so that you could write your own as well. - */ - Singleton( const Singleton& ); - -public: - /** - * Get a handle to the contained instance of the contained class. It is - * a reference. - *@returns A reference to the contained object. - */ - static T &getInstance() - { - static T i; - return i; - } -}; - -#endif diff --git a/src/sptr.cpp b/src/sptr.cpp deleted file mode 100644 index 7f5e894..0000000 --- a/src/sptr.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "sptr.h" diff --git a/src/sptr.h b/src/sptr.h deleted file mode 100644 index deae94d..0000000 --- a/src/sptr.h +++ /dev/null @@ -1,99 +0,0 @@ -#ifndef SPTR_H -#define SPTR_H - -#include <stdint.h> -#include <stdio.h> - -template<typename T> -class SPtr -{ -public: - SPtr() : - pRefCnt( NULL ), - pData( NULL ) - { - } - - ~SPtr() - { - decCount(); - } - - SPtr( const SPtr<T> &src ) : - pRefCnt( src.pRefCnt ), - pData( src.pData ) - { - if( pRefCnt ) - (*pRefCnt) += 1; - } - - SPtr( T *pSrc ) : - pRefCnt( NULL ), - pData( pSrc ) - { - pRefCnt = new int32_t; - (*pRefCnt) = 1; - } - - int32_t count() - { - return *pRefCnt; - } - - T *operator->() const - { - return pData; - } - - T *operator*() const - { - return pData; - } - - SPtr<T> operator=( const SPtr<T> &src ) - { - decCount(); - pRefCnt = src.pRefCnt; - pData = src.pData; - (*pRefCnt) += 1; - - return *this; - } - - bool operator==( const SPtr<T> &src ) - { - return pData == src.pData; - } - - operator bool() - { - return pRefCnt != NULL; - } - - bool isSet() - { - return pRefCnt != NULL; - } - -private: - void decCount() - { - if( pRefCnt ) - { - (*pRefCnt) -= 1; - //printf("Decrementing ref-count to %d\n", *pRefCnt ); - if( (*pRefCnt) == 0 ) - { - delete pRefCnt; - delete pData; - pRefCnt = NULL; - pData = NULL; - } - } - } - - int32_t *pRefCnt; - T *pData; -}; - -#endif diff --git a/src/stack.cpp b/src/stack.cpp deleted file mode 100644 index 8d9565c..0000000 --- a/src/stack.cpp +++ /dev/null @@ -1,33 +0,0 @@ -#include "stack.h" - -void Stack::push( void *data ) -{ - lStackData.append( data ); -} - -void *Stack::top() -{ - return lStackData.getAt( lStackData.getSize()-1 ); -} - -void Stack::pop() -{ - lStackData.deleteAt( lStackData.getSize()-1 ); -} - -void *Stack::poptop() -{ - void *dat = top(); - pop(); - return dat; -} - -bool Stack::isEmpty() -{ - return lStackData.isEmpty(); -} - -void Stack::empty() -{ - lStackData.empty(); -} diff --git a/src/stack.h b/src/stack.h deleted file mode 100644 index 30e2a19..0000000 --- a/src/stack.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef STACK_H -#define STACK_H -#include "linkedlist.h" - -/** An ultra-simple stack implementation that just uses a linked list. - *@author Mike Buland - */ -class Stack -{ -public: - /** Pushes a new value onto the top of the stack. - *@param data A new value for the stack. - *@author Mike Buland - */ - void push( void *data ); - - /** Returns the top value off of the stack, but doesn't remove it from the - * stack. - *@returns The value at the top of the stack. - *@author Mike Buland - */ - void *top(); - - /** Pops the top item off of the stack. - *@author Mike Buland - */ - void pop(); - - /** Gets the top item off of the stack, pops it off the stack, and returns - * it. - *@returns The value at the top of the stack. - *@author Mike Buland - */ - void *poptop(); - - /** Checks if the stack is empty. - *@returns True if the stack is empty, and false if it has things in it. - *@author Mike Buland - */ - bool isEmpty(); - - /** Empty the stack. - *@author Mike Buland - */ - void empty(); - -private: - LinkedList lStackData; /**< The actual stack data. */ -}; -#endif diff --git a/src/staticstring.cpp b/src/staticstring.cpp deleted file mode 100644 index 60f130f..0000000 --- a/src/staticstring.cpp +++ /dev/null @@ -1,282 +0,0 @@ -#include "staticstring.h" -#include "serializer.h" - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> - -StaticString::StaticString() -{ - lpStr = NULL; - nLen = 0; -} - -StaticString::StaticString( int nLength ) -{ - lpStr = new char[nLength+1]; - nLen = nLength; - memset( lpStr, 0, nLength+1 ); -} - -StaticString::StaticString( const char *lpNewStr, int nNewLen ) -{ - lpStr = NULL; - nLen = 0; - setString( lpNewStr, nNewLen ); -} - -StaticString::StaticString( const char *lpNewStr ) -{ - lpStr = NULL; - nLen = 0; - setString( lpNewStr, -1 ); -} - -StaticString::StaticString( StaticString &xSrcStr, int nNewLen ) -{ - lpStr = NULL; - nLen = 0; - setString( xSrcStr, nNewLen ); -} - -StaticString::StaticString( StaticString &xSrcStr ) -{ - lpStr = NULL; - nLen = 0; - setString( xSrcStr, -1 ); -} - -StaticString::StaticString( const StaticString &xSrcStr ) -{ - nLen = xSrcStr.getLength(); - lpStr = new char[nLen]; - memcpy( lpStr, xSrcStr.getString(), nLen ); -} - -StaticString::~StaticString() -{ - if( lpStr != NULL ) delete[] lpStr; -} - -char *StaticString::getString() -{ - return lpStr; -} - -const char *StaticString::getString() const -{ - return lpStr; -} - -int StaticString::getLength() const -{ - return nLen; -} - -void StaticString::setLength( int nNewLength ) -{ - char *lpNewStr = new char[nNewLength+1]; - if( lpStr != NULL ) - { - strncpy( lpNewStr, lpStr, nNewLength ); - } - lpNewStr[nNewLength] = '\0'; - if( lpStr ) - { - delete[] lpStr; - } - lpStr = lpNewStr; - nLen = nNewLength; -} - -void StaticString::setString( const char *lpNewStr, int nNewLen ) -{ - if( lpStr ) - { - delete[] lpStr; - lpStr = NULL; - nLen = 0; - } - if( nNewLen < 0 ) - { - if( lpNewStr == NULL ) return; - nLen = strlen( lpNewStr ); - lpStr = new char[nLen+1]; - strcpy( lpStr, lpNewStr ); - } - else - { - nLen = nNewLen; - lpStr = new char[nLen+1]; - memset( lpStr, 0, nLen+1 ); - if( lpNewStr ) - strncpy( lpStr, lpNewStr, nNewLen ); - } -} - -void StaticString::setString( StaticString &sNewStr, int nNewLen ) -{ - if( lpStr ) - { - delete[] lpStr; - lpStr = NULL; - nLen = 0; - } - if( nNewLen < 0 ) - { - if( sNewStr.lpStr == NULL ) return; - nLen = sNewStr.nLen; - lpStr = new char[nLen+1]; - strcpy( lpStr, sNewStr.lpStr ); - } - else - { - nLen = nNewLen; - lpStr = new char[nLen+1]; - memset( lpStr, 0, nLen+1 ); - if( sNewStr.lpStr ) - strncpy( lpStr, sNewStr.lpStr, nNewLen ); - } -} - -StaticString &StaticString::operator=( StaticString &lpOtherStr ) -{ - setString( lpOtherStr ); - - return *this; -} - -StaticString &StaticString::operator=( std::string &lpOtherStr ) -{ - setString( lpOtherStr.c_str() ); - - return *this; -} - -StaticString &StaticString::operator=( const char *lpNewStr ) -{ - setString( lpNewStr ); - - return *this; -} - -StaticString::operator const char *() -{ - return lpStr; -} - -char StaticString::getAt( unsigned int nIndex ) -{ - if( nIndex < 0 || nIndex >= nLen ) - return '\0'; - - return lpStr[nIndex]; -} - -void StaticString::setAt( unsigned int nIndex, char cVal ) -{ - if( nIndex < 0 || nIndex >= nLen ) - return; - - lpStr[nIndex] = cVal; -} - -char &StaticString::operator[]( unsigned int nIndex ) -{ - if( nIndex < 0 || nIndex >= nLen ) - return lpStr[0]; - - return lpStr[nIndex]; -} - -StaticString::operator int() -{ - return nLen; -} - -char *StaticString::operator+( int nAmnt ) -{ - return lpStr + nAmnt; -} - -char *StaticString::operator-( int nAmnt ) -{ - return lpStr - nAmnt; -} - -void StaticString::clear() -{ - memset( lpStr, 0, nLen+1 ); -} - -void StaticString::serialize( Serializer &ar ) -{ - if( ar.isLoading() ) - { - ar >> nLen; - setLength( nLen ); - ar.read( lpStr, nLen ); - } - else - { - ar << nLen; - ar.write( lpStr, nLen ); - } -} - -bool StaticString::operator==( const char *str ) -{ - const char *a = str, *b = lpStr; - for(; *a == *b; a++, b++ ) if( *a == '\0' && *b == '\0' ) return true; - return false; -} - -bool StaticString::operator==( StaticString &str ) -{ - const char *a = str.lpStr, *b = lpStr; - for(; *a == *b; a++, b++ ) if( *a == '\0' && *b == '\0' ) return true; - return false; -} - -bool StaticString::operator!=( const char *str ) -{ - const char *a = str, *b = lpStr; - for(; *a == *b; a++, b++ ) if( *a == '\0' && *b == '\0' ) return false; - return true; -} - -bool StaticString::operator!=( StaticString &str ) -{ - const char *a = str.lpStr, *b = lpStr; - for(; *a == *b; a++, b++ ) if( *a == '\0' && *b == '\0' ) return false; - return true; -} -/* -unsigned long int StaticString::getHashCode() -{ - unsigned long int nPos = nLen; - unsigned long int j = 0; - for( const char *s = (const char *)lpStr; j< nLen; s++, j++ ) - { - nPos = *s + (nPos << 6) + (nPos << 16) - nPos; - } - return nPos; -} - -bool StaticString::compareForHash( Hashable &other ) -{ - if( ((StaticString &)other).nLen != nLen ) - return false; - - const char *a = ((StaticString &)other).lpStr; - const char *b = lpStr; - if( a == b ) - return true; - - for( unsigned long j = 0; j < nLen; j++, a++, b++ ) - if( *a != *b ) - return false; - - return true; -} -*/ diff --git a/src/staticstring.h b/src/staticstring.h deleted file mode 100644 index 4c3f7b8..0000000 --- a/src/staticstring.h +++ /dev/null @@ -1,63 +0,0 @@ -#ifndef STATIC_STRING_H -#define STATIC_STRING_H - -#include <string> -#include "serializable.h" -//#include "hashable.h" - -/** - * Simple string managing class. Allows for dynamically allocated string data - * along with some minor caching to speed things up when accessing your - * string data. Really designed for making copies of strings easy and safe, - * and making accessing meta-info like length fast and reliable as well. - *@author Mike Buland - */ -class StaticString : public Serializable/*, public Hashable*/ -{ -public: - StaticString(); - StaticString( const char *lpNewStr, int nNewLen ); - StaticString( const char *lpNewStr ); - StaticString( StaticString &xSrcStr, int nNewLen ); - StaticString( StaticString &xSrcStr ); - StaticString( const StaticString &xSrcStr ); - StaticString( int nLength ); - virtual ~StaticString(); - - char *getString(); - const char *getString() const; - int getLength() const; - void setLength( int nNewLength ); - - void setString( const char *lpNewStr, int nNewLen=-1 ); - void setString( StaticString &sNewStr, int nNewLen=-1 ); - - char getAt( unsigned int nIndex ); - void setAt( unsigned int nIndex, char cVal ); - - class StaticString &operator=( class StaticString &lpOtherStr ); - class StaticString &operator=( std::string &lpOtherStr ); - class StaticString &operator=( const char *lpNewStr ); - operator const char *(); - char &operator[]( unsigned int nIndex ); - operator int(); - char *operator+( int nAmnt ); - char *operator-( int nAmnt ); - bool operator==( const char *str ); - bool operator==( StaticString &str ); - bool operator!=( const char *str ); - bool operator!=( StaticString &str ); - - void clear(); - - virtual void serialize( class Serializer &ar ); - - //virtual unsigned long int getHashCode(); - //virtual bool compareForHash( Hashable &other ); - -private: - char *lpStr; - uint32_t nLen; -}; - -#endif diff --git a/src/stream.cpp b/src/stream.cpp deleted file mode 100644 index 856a58d..0000000 --- a/src/stream.cpp +++ /dev/null @@ -1,10 +0,0 @@ -#include "stream.h" - -Stream::Stream() -{ -} - -Stream::~Stream() -{ -} - diff --git a/src/stream.h b/src/stream.h deleted file mode 100644 index e086e28..0000000 --- a/src/stream.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef STREAM_H -#define STREAM_H - -#include <stdint.h> -#include <stdio.h> - -class Stream -{ -public: - Stream(); - virtual ~Stream(); - - virtual void close() = 0; - virtual size_t read( char *pBuf, size_t nBytes ) = 0; - virtual size_t write( const char *pBuf, size_t nBytes ) = 0; - - virtual long tell() = 0; - virtual void seek( long offset ) = 0; - virtual void setPos( long pos ) = 0; - virtual void setPosEnd( long pos ) = 0; - virtual bool isEOS() = 0; - -private: - -}; - -#endif diff --git a/src/stringrep.cpp b/src/stringrep.cpp deleted file mode 100644 index a505f8a..0000000 --- a/src/stringrep.cpp +++ /dev/null @@ -1,19 +0,0 @@ -#include "stringrep.h" - -int32_t stringlen( const char *s ) -{ - for( int32_t i = 0;; i++ ) - if( !s[i] ) - return i; -} - -char *stringdup( const char *s ) -{ - int len = stringlen( s ); - char *r = new char[len+1]; - for( int j = 0; j <= len; j++ ) - r[j] = s[j]; - - return r; -} - diff --git a/src/stringrep.h b/src/stringrep.h deleted file mode 100644 index eaa4a12..0000000 --- a/src/stringrep.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef STRING_REP_H -#define STRING_REP_H - -#include <stdint.h> - -/** - * Calculates the length of a string. - */ -int32_t stringlen( const char *s ); - -/** - * Identicle to strdup, which isn't available everywhere, but uses c++ memory - * facilities. Remember to use delete[] when freeing the returned string. - */ -char *stringdup( const char *s ); - -#endif diff --git a/src/tests/clistress.cpp b/src/tests/clistress.cpp deleted file mode 100644 index 6b0ac66..0000000 --- a/src/tests/clistress.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include "connection.h" - -int main() -{ - Connection c; - - c.open("localhost", 4001 ); - - c.appendOutput("w"); - c.writeOutput(); - - c.waitForInput( 6, 5, 0 ); - - printf("read: %s\n", c.getInput() ); - - c.close(); - - return 0; -} - diff --git a/src/tests/confpair.cpp b/src/tests/confpair.cpp deleted file mode 100644 index fb1b0d3..0000000 --- a/src/tests/confpair.cpp +++ /dev/null @@ -1,19 +0,0 @@ -#include "confpair.h" -#include <iostream> - -using namespace std; - -int main() -{ - ConfPair<float> p1("DebugMode"); - p1.value() = 12; - cout << p1.value() << "\n"; - p1.value() = 55; - cout << p1.value() << "\n"; - - ConfPairBase &p = p1; - - p = "33.12"; - cout << p.getAsString(); -} - diff --git a/src/tests/connect.cpp b/src/tests/connect.cpp deleted file mode 100644 index a9fca64..0000000 --- a/src/tests/connect.cpp +++ /dev/null @@ -1,38 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <fcntl.h> -#include "connection.h" - -int main() -{ - Connection c; - c.open("127.0.0.1", 12457 ); - - { - int newSocket = c.getSocket(); - int flags; - - flags = fcntl(newSocket, F_GETFL, 0); - flags |= O_NONBLOCK; - if (fcntl(newSocket, F_SETFL, flags) < 0) - { - return false; - } - } - - for( int i = 0; i < 50; i++ ) - { - usleep( 100000 ); - int nbytes = c.readInput(); - if( nbytes == 0 ) - printf("0 bytes, EOF?\n"); - else - printf("Got %d bytes, whacky...\n", nbytes ); - } - - c.close(); - - return 0; -} - diff --git a/src/tests/exception.cpp b/src/tests/exception.cpp deleted file mode 100644 index 6417692..0000000 --- a/src/tests/exception.cpp +++ /dev/null @@ -1,16 +0,0 @@ -#include <iostream> -#include "exceptions.h" - -int main() -{ - try - { - throw ExceptionBase( 42, "There was an error on line: %d", __LINE__ ); - } - catch( ExceptionBase &e ) - { - std::cout << "Error "<< e.getErrorCode() << ": " << e.what() << "\n"; - } - - throw ExceptionBase( 112, "This exception wasn't caught!"); -} diff --git a/src/tests/formula.cpp b/src/tests/formula.cpp deleted file mode 100644 index 976b039..0000000 --- a/src/tests/formula.cpp +++ /dev/null @@ -1,13 +0,0 @@ -#include "formula.h" - -int main( int argc, char *argv[] ) -{ - if( argc < 2 ) return 0; - - Formula f; - double dOut = f.run( argv[1] ); - printf("%s = %f\n", argv[1], dOut ); - - return 0; -} - diff --git a/src/tests/fstring.cpp b/src/tests/fstring.cpp deleted file mode 100644 index 271738c..0000000 --- a/src/tests/fstring.cpp +++ /dev/null @@ -1,48 +0,0 @@ -#include "hash.h" -#include "fstring.h" - -FString genThing() -{ - FString bob; - bob.append("ab "); - bob += "cd "; - bob += "efg"; - - printf("---bob------\n%08X: %s\n", (unsigned int)bob.c_str(), bob.c_str() ); - return bob; -} - -void thing( FString str ) -{ - printf("Hey: %s\n", str.c_str() ); -} - -#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() ); -int main( int argc, char *argv ) -{ - FString str("th"); - - str.prepend("Hello "); - str.append("ere."); - - FString str2( str ); - pem; - str += " What's up?"; - pem; - str2 += " How are you?"; - pem; - str = str2; - pem; - - str2 = genThing(); - pem; - - str = str2; - pem; - - thing( str2 ); - thing("test."); - - printf("%d == %d\n", __calcHashCode( str ), __calcHashCode( str.c_str() ) ); -} - diff --git a/src/tests/hash.cpp b/src/tests/hash.cpp deleted file mode 100644 index 2fc6968..0000000 --- a/src/tests/hash.cpp +++ /dev/null @@ -1,116 +0,0 @@ -#include "hash.h" -#include "staticstring.h" - -int main() -{ - const char *names[]={ - "Homer the Great", - "And Maggie Makes Three", - "Bart's Comet", - "Homie The Clown", - "Bart Vs Australia", - "Homer vs Patty and Selma", - "A star is burns", - "Lisa's Wedding", - "Two Dozen and One Greyhounds", - "The PTA Disbands", - "Round Springfield", - "The Springfield connection", - "Lemon of Troy", - "Who Shot Mr. Burns (Pt. 1)", - "Who Shot Mr. Burns (pt. 2)", - "Radioactive Man", - "Home Sweet Homediddly-dum-doodly", - "Bart Sells His Soul", - "Lisa the Vegetarian", - "Treehouse of horror VI", - "King Size Homer", - "Mother Simpson", - "Sideshow Bob's Last Gleaming", - "The Simpson's 138th Show Spectacular", - "Marge Be Not Proud", - "Team Homer", - "Two Bad Neighbors", - "Scenes From the Class Struggle in Springfield", - "Bart the Fink", - "Lisa the Iconoclast", - "Homer the Smithers", - "The Day the Violence Died", - "A Fish Called Selma", - "Bart on the road", - "22 Short Films about Springfield", - "The Curse of the Flying Hellfish", - "Much Apu about Nothing", - "Homerpalooza", - "The Summer of 4 Ft 2", - "Treehouse of Horror VII", - "You Only Move Twice", - "The Homer They Fall", - "Burns Baby Burns", - "Bart After Dark", - "A Millhouse Divided", - "Lisas Date With Destiny", - "Hurricane Neddy", - "The Mysterious Voyage of Our Homer", - "The Springfield Files", - "The Twisted World of Marge Simpson", - "Mountain of Madness", - NULL - }; - - Hash<const char *, int> sTest; - - printf("Inserting\n-------------------\n\n"); - for( int j = 0; j < 33; j++ ) - { - sTest[names[j]] = j; - } - - printf("Test1: %d, Test2: %d\n", sTest.has("Lemon of Troy"), sTest.has(std::string("Lemon of Troy").c_str() ) ); - - sTest.has(std::string("Lemon of Troy").c_str() ); - - printf("Getting\n-------------------\n\n"); - - sTest.erase("Homer the Great"); - sTest["Bart's Comet"].erase(); - - for( Hash<const char *, int>::iterator i = sTest.begin(); - i != sTest.end(); i++ ) - { - Hash<const char *, int>::iterator j = i; - printf("%d: %s\n", (*j).second, (*j).first ); - } - - printf("Testing\n-------------------\n\n"); - for( int j = 0; j < 33; j++ ) - { - if( sTest.has(names[j]) ) - { - if( sTest[names[j]] != j ) - { - printf("'%s' should be %d, is %d\n", - names[j], j, - sTest[names[j]].value() - ); - } - } - else - { - printf("Missing element %d, '%s'\n", j, names[j] ); - } - } - - printf("Clearing\n-------------------\n\n"); - - sTest.clear(); - - for( Hash<const char *, int>::iterator i = sTest.begin(); - i != sTest.end(); i++ ) - { - Hash<const char *, int>::iterator j = i; - printf("%d: %s\n", (*j).second, (*j).first ); - } - -} - diff --git a/src/tests/hashtest.cpp b/src/tests/hashtest.cpp deleted file mode 100644 index eaa84a0..0000000 --- a/src/tests/hashtest.cpp +++ /dev/null @@ -1,107 +0,0 @@ -#include <stdio.h> -#include <iostream> -#include "hashtable.h" -#include "hashfunctioncasestring.h" - -int main() -{ - const char *names[]={ - "Homer the Great", - "And Maggie Makes Three", - "Bart's Comet", - "Homie The Clown", - "Bart Vs Australia", - "Homer vs Patty and Selma", - "A star is burns", - "Lisa's Wedding", - "Two Dozen and One Greyhounds", - "The PTA Disbands", - "Round Springfield", - "The Springfield connection", - "Lemon of Troy", - "Who Shot Mr. Burns (Pt. 1)", - "Who Shot Mr. Burns (pt. 2)", - "Radioactive Man", - "Home Sweet Homediddly-dum-doodly", - "Bart Sells His Soul", - "Lisa the Vegetarian", - "Treehouse of horror VI", - "King Size Homer", - "Mother Simpson", - "Sideshow Bob's Last Gleaming", - "The Simpson's 138th Show Spectacular", - "Marge Be Not Proud", - "Team Homer", - "Two Bad Neighbors", - "Scenes From the Class Struggle in Springfield", - "Bart the Fink", - "Lisa the Iconoclast", - "Homer the Smithers", - "The Day the Violence Died", - "A Fish Called Selma", - "Bart on the road", - "22 Short Films about Springfield", - "The Curse of the Flying Hellfish", - "Much Apu about Nothing", - "Homerpalooza", - "The Summer of 4 Ft 2", - "Treehouse of Horror VII", - "You Only Move Twice", - "The Homer They Fall", - "Burns Baby Burns", - "Bart After Dark", - "A Millhouse Divided", - "Lisas Date With Destiny", - "Hurricane Neddy", - "The Mysterious Voyage of Our Homer", - "The Springfield Files", - "The Twisted World of Marge Simpson", - "Mountain of Madness", - NULL - }; - - HashTable h( new HashFunctionCaseString(), 5, false ); - - int j; - printf("Inserting...\n"); - for( j = 0; j < 10; j++ ) - { - h.insert( names[j], (void *)(j+1) ); - h.insert( names[j], (void *)(j+1) ); - printf("Capacity: %lu, Size: %lu, Load: %f\n", - h.getCapacity(), - h.getSize(), - h.getLoad() - ); - } - - for( j = 0; j < 10; j++ ) - { - printf("\"%s\" = %d\n", names[j], (int)h[names[j]] ); - } - - printf("\nDeleting some...\n"); - - for( int k = 0; k < 7; k++ ) - { - h.del( names[k] ); - //h.insert( names[j], (void *)(j+1) ); - printf("Capacity: %lu, Size: %lu, Load: %f\n", - h.getCapacity(), - h.getSize(), - h.getLoad() - ); - } - - printf("\nInserting more...\n"); - - for( ; names[j] != NULL; j++ ) - { - h.insert( names[j], (void *)(j+1) ); - printf("Capacity: %lu, Size: %lu, Load: %f\n", - h.getCapacity(), - h.getSize(), - h.getLoad() - ); - } -} diff --git a/src/tests/hashtest2.cpp b/src/tests/hashtest2.cpp deleted file mode 100644 index 74700fd..0000000 --- a/src/tests/hashtest2.cpp +++ /dev/null @@ -1,15 +0,0 @@ -#include "hash.h" -#include <string.h> - -int main() -{ - char *a, *b; - a = new char[10]; - b = new char[10]; - strcpy( a, "Hey there"); - strcpy( b, "Hey there"); - printf("Same: %s\n", __cmpHashKeys( a, b )?"yes":"no"); - - return 0; -} - diff --git a/src/tests/httpsrv/httpconnectionmonitor.cpp b/src/tests/httpsrv/httpconnectionmonitor.cpp deleted file mode 100644 index 51d82f3..0000000 --- a/src/tests/httpsrv/httpconnectionmonitor.cpp +++ /dev/null @@ -1,88 +0,0 @@ -#include "httpconnectionmonitor.h" -#include "http.h" -#include "exceptions.h" -#include <sys/stat.h> - -HttpConnectionMonitor::HttpConnectionMonitor() -{ -} - -HttpConnectionMonitor::~HttpConnectionMonitor() -{ -} - -bool HttpConnectionMonitor::onNewConnection( Connection *pCon, int nPort ) -{ - printf("Got connection on port %d\n", nPort ); - - try - { - pCon->readInput( 60, 0 ); - printf("#######################\n%s\n#######################\n", pCon->getInput() ); - - Http hp( pCon ); - while( hp.parseRequest() == false ); - printf("Done parsing.\n\n"); - - if( hp.getRequestType() == Http::reqGet ) - { - printf("\"\"\"%s\"\"\"\n", hp.getRequestURI() ); - if( !strcmp( hp.getRequestURI(), "/" ) ) - { - 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>"); - hp.buildResponse(); - hp.setResponseContent( - "text/html", - content.c_str(), - content.size() - ); - hp.sendResponse(); - } - else - { - 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>"); - hp.buildResponse( 404, "File not found."); - hp.setResponseContent( - "text/html", - content.c_str(), - content.size() - ); - hp.sendResponse(); - } - } - else - { - printf("Non get: %s\n", hp.getRequestTypeStr() ); - pCon->appendOutput("HTTP/1.1 100 Continue\r\n\r\n"); - } - pCon->writeOutput(); - //for( int j = 0; j < 50; j++ ) - { - pCon->readInput( 1, 0 ); - //printf("Size so far: %d\n", pCon->getInputAmnt() ); - } - - if( pCon->hasInput() ) - { - std::string s( pCon->getInput(), pCon->getInputAmnt() ); - - pCon->printInputDebug(); - //printf("Reamining data\n==============\n%s\n==============\n", - // s.c_str() ); - } - - pCon->disconnect(); - } - catch( ConnectionException &e ) - { - printf("Connection: %s\n", e.what() ); - } - - return true; -} - -bool HttpConnectionMonitor::onClosedConnection( Connection *pCon ) -{ - return true; -} - diff --git a/src/tests/httpsrv/httpconnectionmonitor.h b/src/tests/httpsrv/httpconnectionmonitor.h deleted file mode 100644 index 30c0afd..0000000 --- a/src/tests/httpsrv/httpconnectionmonitor.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef HTTPCONNECTIONMONITOR_H -#define HTTPCONNECTIONMONITOR_H - -#include "connectionmonitor.h" - -class HttpConnectionMonitor : public ConnectionMonitor -{ -public: - HttpConnectionMonitor(); - ~HttpConnectionMonitor(); - - bool onNewConnection( Connection *pCon, int nPort ); - bool onClosedConnection( Connection *pCon ); -}; - -#endif diff --git a/src/tests/httpsrv/main.cpp b/src/tests/httpsrv/main.cpp deleted file mode 100644 index 2f1563c..0000000 --- a/src/tests/httpsrv/main.cpp +++ /dev/null @@ -1,22 +0,0 @@ -#include "connectionmanager.h" -#include "httpconnectionmonitor.h" - -int main() -{ - printf("Starting server...\n"); - - ConnectionManager srv; - HttpConnectionMonitor http; - - srv.setConnectionMonitor( &http ); - - printf("Listening on port 7331\n"); - srv.startServer( 7331 ); - - for(;;) - { - srv.scanConnections( 5000, false ); - } - - return 0; -} diff --git a/src/tests/log.cpp b/src/tests/log.cpp deleted file mode 100644 index d7cfa0b..0000000 --- a/src/tests/log.cpp +++ /dev/null @@ -1,29 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> -#include <iostream> -#include "multilog.h" -#include "multilogtext.h" - -class Test -{ -public: - Test() - { - MultiLineLog( 4, "Test init'd\n"); - } -}; - -int main() -{ - MultiLog &xLog = MultiLog::getInstance(); - - xLog.LineLog( 2, "Hello again"); - - MultiLog::getInstance().addChannel( - new MultiLogText( STDOUT_FILENO, "%02y-%02m-%02d %02h:%02M:%02s: %t" ) - ); - - MultiLineLog( MultiLog::LError, "Hi there!"); - Test t; -} - diff --git a/src/tests/md5test.cpp b/src/tests/md5test.cpp deleted file mode 100644 index 6f832df..0000000 --- a/src/tests/md5test.cpp +++ /dev/null @@ -1,19 +0,0 @@ -#include <stdio.h> -#include <string.h> -#include "md5.h" - -int main() -{ - md5 mproc; - md5sum sum; - char hexstr[33]; - - memset( hexstr, 0, 33 ); - - mproc.sumString( &sum, "qwertyuiopasdfgh" ); - mproc.sumToHex( &sum, hexstr ); - printf("sum: %s\n", hexstr ); - printf("chk: 1ebfc043d8880b758b13ddc8aa1638ef\n"); - - return 0; -} diff --git a/src/tests/ordhash.cpp b/src/tests/ordhash.cpp deleted file mode 100644 index f1d96ec..0000000 --- a/src/tests/ordhash.cpp +++ /dev/null @@ -1,48 +0,0 @@ -#include "ordhash.h" -#include <string> - -typedef struct eldef -{ - eldef( int a, int b, const std::string &c ) : - id( a ), nSequence( b ), sName( c ) {} - int id; - int nSequence; - std::string sName; -} eldef; - -struct seqcmp -{ - bool operator()( eldef **a, eldef **b ) - { - return (*a)->nSequence < (*b)->nSequence; - } -}; - -struct namcmp -{ - bool operator()( eldef **a, eldef **b ) - { - return (*a)->sName < (*b)->sName; - } -}; - -typedef OrdHash<int, eldef, seqcmp> AHash; -//typedef OrdHash<int, eldef, namcmp> AHash; - -int main() -{ - AHash hsh; - hsh[1] = eldef( 0, 43, "Bob"); - hsh[4] = eldef( 1, 443, "Abby"); - hsh[2] = eldef( 2, 1, "Name"); - hsh[5] = eldef( 3, 0, "Catagory"); - hsh[32] = eldef( 4, 12, "Epilogue"); - - for( AHash::iterator i = hsh.begin(); i != hsh.end(); i++ ) - { - eldef e = (*i).second; - printf("%d, %d, %s\n", e.id, e.nSequence, e.sName.c_str() ); - } - -} - diff --git a/src/tests/param.cpp b/src/tests/param.cpp deleted file mode 100644 index a4d2824..0000000 --- a/src/tests/param.cpp +++ /dev/null @@ -1,46 +0,0 @@ -#include "param.h" -#include <stdio.h> - -Param::Param() -{ - addHelpBanner("param - A test of the libbu++ parameter systems\n" - "Enjoy with care and caution\n\nTest stuff:\n"); - addParam( "name", 's', mkproc( Param::printStuff ), &str, "Test a param param" ); - //addParam( "name", &str ); - addParam( "job", 'U', mkproc( Param::printStuff ), "Test a paramless param" ); - - addHelpBanner("\nInformational:\n"); - addParam( "help", mkproc( ParamProc::help ), "Help!" ); - - addHelpBanner("\nThanks for trying my test!\n\n"); -} - -Param::~Param() -{ -} - -int Param::printStuff( int argc, char *argv[] ) -{ - printf("------------%02d-------------\n", argc ); - for( int j = 0; j < argc; j++ ) - { - printf("%d: %s\n", j, argv[j] ); - } - printf("---------------------------\n" ); - printf("SETVAR===\"%s\"\n", str.c_str() ); - - return 1; -} - -int main( int argc, char *argv[] ) -{ - if( argc == 1 ) - { - printf("You have to enter some parameter, try '--help'\n\n"); - return 0; - } - - Param p; - p.process( argc, argv ); -} - diff --git a/src/tests/param.h b/src/tests/param.h deleted file mode 100644 index 2756b69..0000000 --- a/src/tests/param.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef PARAM_H -#define PARAM_H - -#include <stdint.h> - -#include "paramproc.h" - -class Param : public ParamProc -{ -public: - Param(); - virtual ~Param(); - -private: - int printStuff( int argc, char *argv[] ); - - std::string str; - uint32_t uint32; -}; - -#endif diff --git a/src/tests/plugin/main.cpp b/src/tests/plugin/main.cpp deleted file mode 100644 index 51c8390..0000000 --- a/src/tests/plugin/main.cpp +++ /dev/null @@ -1,14 +0,0 @@ -#include "plugger.h" -#include "plugin.h" - -int main() -{ - Plugger<Plugin> p; - - p.registerExternalPlugin( "./guy.so", "Guy" ); - - Plugin *t = p.instantiate( "Guy" ); - - p.destroy( t ); -} - diff --git a/src/tests/plugin/plugin.cpp b/src/tests/plugin/plugin.cpp deleted file mode 100644 index ea558fd..0000000 --- a/src/tests/plugin/plugin.cpp +++ /dev/null @@ -1,10 +0,0 @@ -#include "plugin.h" - -Plugin::Plugin() -{ -} - -Plugin::~Plugin() -{ -} - diff --git a/src/tests/plugin/plugin.h b/src/tests/plugin/plugin.h deleted file mode 100644 index f726867..0000000 --- a/src/tests/plugin/plugin.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef PLUGIN_H -#define PLUGIN_H - -class Plugin -{ -public: - Plugin(); - virtual ~Plugin(); - -private: - -}; - -#endif diff --git a/src/tests/qsort.cpp b/src/tests/qsort.cpp deleted file mode 100644 index 28c6f03..0000000 --- a/src/tests/qsort.cpp +++ /dev/null @@ -1,228 +0,0 @@ -#define _QSORT_SWAP(a, b, t) ((void)((t = *a), (*a = *b), (*b = t))) - -/* Discontinue quicksort algorithm when partition gets below this size. - This particular magic number was chosen to work best on a Sun 4/260. */ -#define _QSORT_MAX_THRESH 4 - -/* Stack node declarations used to store unfulfilled partition obligations - * (inlined in QSORT). -typedef struct { - QSORT_TYPE *_lo, *_hi; -} qsort_stack_node; - */ - -/* The next 4 #defines implement a very fast in-line stack abstraction. */ -/* The stack needs log (total_elements) entries (we could even subtract - log(MAX_THRESH)). Since total_elements has type unsigned, we get as - upper bound for log (total_elements): - bits per byte (CHAR_BIT) * sizeof(unsigned). */ -#define _QSORT_STACK_SIZE (8 * sizeof(unsigned)) -#define _QSORT_PUSH(top, low, high) \ - (((top->_lo = (low)), (top->_hi = (high)), ++top)) -#define _QSORT_POP(low, high, top) \ - ((--top, (low = top->_lo), (high = top->_hi))) -#define _QSORT_STACK_NOT_EMPTY (_stack < _top) - - -/* Order size using quicksort. This implementation incorporates - four optimizations discussed in Sedgewick: - - 1. Non-recursive, using an explicit stack of pointer that store the - next array partition to sort. To save time, this maximum amount - of space required to store an array of SIZE_MAX is allocated on the - stack. Assuming a 32-bit (64 bit) integer for size_t, this needs - only 32 * sizeof(stack_node) == 256 bytes (for 64 bit: 1024 bytes). - Pretty cheap, actually. - - 2. Chose the pivot element using a median-of-three decision tree. - This reduces the probability of selecting a bad pivot value and - eliminates certain extraneous comparisons. - - 3. Only quicksorts TOTAL_ELEMS / MAX_THRESH partitions, leaving - insertion sort to order the MAX_THRESH items within each partition. - This is a big win, since insertion sort is faster for small, mostly - sorted array segments. - - 4. The larger of the two sub-partitions is always pushed onto the - stack first, with the algorithm then concentrating on the - smaller partition. This *guarantees* no more than log (total_elems) - stack size is needed (actually O(1) in this case)! */ - -/* The main code starts here... */ - -template<typename QSORT_TYPE, typename QSORT_LTT> -void qsrt( QSORT_TYPE *QSORT_BASE, int QSORT_NELT ) -{ - QSORT_LTT QSORT_LT; - QSORT_TYPE *const _base = (QSORT_BASE); - const unsigned _elems = (QSORT_NELT); - QSORT_TYPE _hold; - - /* Don't declare two variables of type QSORT_TYPE in a single - * statement: eg `TYPE a, b;', in case if TYPE is a pointer, - * expands to `type* a, b;' wich isn't what we want. - */ - - if (_elems > _QSORT_MAX_THRESH) { - QSORT_TYPE *_lo = _base; - QSORT_TYPE *_hi = _lo + _elems - 1; - struct { - QSORT_TYPE *_hi; QSORT_TYPE *_lo; - } _stack[_QSORT_STACK_SIZE], *_top = _stack + 1; - - while (_QSORT_STACK_NOT_EMPTY) { - QSORT_TYPE *_left_ptr; QSORT_TYPE *_right_ptr; - - /* Select median value from among LO, MID, and HI. Rearrange - LO and HI so the three values are sorted. This lowers the - probability of picking a pathological pivot value and - skips a comparison for both the LEFT_PTR and RIGHT_PTR in - the while loops. */ - - QSORT_TYPE *_mid = _lo + ((_hi - _lo) >> 1); - - if (QSORT_LT (_mid, _lo)) - _QSORT_SWAP (_mid, _lo, _hold); - if (QSORT_LT (_hi, _mid)) - _QSORT_SWAP (_mid, _hi, _hold); - else - goto _jump_over; - if (QSORT_LT (_mid, _lo)) - _QSORT_SWAP (_mid, _lo, _hold); - _jump_over:; - - _left_ptr = _lo + 1; - _right_ptr = _hi - 1; - - /* Here's the famous ``collapse the walls'' section of quicksort. - Gotta like those tight inner loops! They are the main reason - that this algorithm runs much faster than others. */ - do { - while (QSORT_LT (_left_ptr, _mid)) - ++_left_ptr; - - while (QSORT_LT (_mid, _right_ptr)) - --_right_ptr; - - if (_left_ptr < _right_ptr) { - _QSORT_SWAP (_left_ptr, _right_ptr, _hold); - if (_mid == _left_ptr) - _mid = _right_ptr; - else if (_mid == _right_ptr) - _mid = _left_ptr; - ++_left_ptr; - --_right_ptr; - } - else if (_left_ptr == _right_ptr) { - ++_left_ptr; - --_right_ptr; - break; - } - } while (_left_ptr <= _right_ptr); - - /* Set up pointers for next iteration. First determine whether - left and right partitions are below the threshold size. If so, - ignore one or both. Otherwise, push the larger partition's - bounds on the stack and continue sorting the smaller one. */ - - if (_right_ptr - _lo <= _QSORT_MAX_THRESH) { - if (_hi - _left_ptr <= _QSORT_MAX_THRESH) - /* Ignore both small partitions. */ - _QSORT_POP (_lo, _hi, _top); - else - /* Ignore small left partition. */ - _lo = _left_ptr; - } - else if (_hi - _left_ptr <= _QSORT_MAX_THRESH) - /* Ignore small right partition. */ - _hi = _right_ptr; - else if (_right_ptr - _lo > _hi - _left_ptr) { - /* Push larger left partition indices. */ - _QSORT_PUSH (_top, _lo, _right_ptr); - _lo = _left_ptr; - } - else { - /* Push larger right partition indices. */ - _QSORT_PUSH (_top, _left_ptr, _hi); - _hi = _right_ptr; - } - } - } - - /* Once the BASE array is partially sorted by quicksort the rest - is completely sorted using insertion sort, since this is efficient - for partitions below MAX_THRESH size. BASE points to the - beginning of the array to sort, and END_PTR points at the very - last element in the array (*not* one beyond it!). */ - - { - QSORT_TYPE *const _end_ptr = _base + _elems - 1; - QSORT_TYPE *_tmp_ptr = _base; - register QSORT_TYPE *_run_ptr; - QSORT_TYPE *_thresh; - - _thresh = _base + _QSORT_MAX_THRESH; - if (_thresh > _end_ptr) - _thresh = _end_ptr; - - /* Find smallest element in first threshold and place it at the - array's beginning. This is the smallest array element, - and the operation speeds up insertion sort's inner loop. */ - - for (_run_ptr = _tmp_ptr + 1; _run_ptr <= _thresh; ++_run_ptr) - if (QSORT_LT (_run_ptr, _tmp_ptr)) - _tmp_ptr = _run_ptr; - - if (_tmp_ptr != _base) - _QSORT_SWAP (_tmp_ptr, _base, _hold); - - /* Insertion sort, running from left-hand-side - * up to right-hand-side. */ - - _run_ptr = _base + 1; - while (++_run_ptr <= _end_ptr) { - _tmp_ptr = _run_ptr - 1; - while (QSORT_LT (_run_ptr, _tmp_ptr)) - --_tmp_ptr; - - ++_tmp_ptr; - if (_tmp_ptr != _run_ptr) { - QSORT_TYPE *_trav = _run_ptr + 1; - while (--_trav >= _run_ptr) { - QSORT_TYPE *_hi; QSORT_TYPE *_lo; - _hold = *_trav; - - for (_hi = _lo = _trav; --_lo >= _tmp_ptr; _hi = _lo) - *_hi = *_lo; - *_hi = _hold; - } - } - } - } - -} - - -struct cc -{ - bool operator()( int *a, int *b ) - { - return *a < *b; - } -}; - -#include <stdio.h> - -int main() -{ - int lst[] = { 43, 1, 342, 12, 491, 32, 12321, 32, 3, -3 }; - - for( int j = 0; j < 10; j++ ) - printf("%s%d", (j>0)?", ":"", lst[j] ); - printf("\n"); - qsrt<int, cc>( lst, 10 ); - for( int j = 0; j < 10; j++ ) - printf("%s%d", (j>0)?", ":"", lst[j] ); - printf("\n"); -} - diff --git a/src/tests/sbuffer.cpp b/src/tests/sbuffer.cpp deleted file mode 100644 index 02798cb..0000000 --- a/src/tests/sbuffer.cpp +++ /dev/null @@ -1,27 +0,0 @@ -#include "sbuffer.h" - -int main() -{ - SBuffer buf; - - buf.write("abcdefg", 7 ); - - printf("tell: %ld\n", buf.tell() ); - - char abuf[6]; - int nRead; - nRead = buf.read( abuf, 5 ); - abuf[nRead] = '\0'; - printf("Read %d bytes \"%s\"\n", nRead, abuf ); - - buf.setPos( 0 ); - nRead = buf.read( abuf, 5 ); - abuf[nRead] = '\0'; - printf("Read %d bytes \"%s\"\n", nRead, abuf ); - - nRead = buf.read( abuf, 5 ); - abuf[nRead] = '\0'; - printf("Read %d bytes \"%s\"\n", nRead, abuf ); - -} - diff --git a/src/tests/serialize.cpp b/src/tests/serialize.cpp deleted file mode 100644 index e233704..0000000 --- a/src/tests/serialize.cpp +++ /dev/null @@ -1,30 +0,0 @@ -#include "serializerbinary.h" -#include "staticstring.h" -#include <stdio.h> -#include <string> - -int main() -{ - int32_t one; - double two; - bool three; - StaticString s("Test string!"); - std::string ss("Another test string"); - SerializerBinary ar("hello.dat", false); - ar << (int)85; - ar << (double)2.63434; - ar << false; - ar << ss; - ar.close(); - - one = 0; two = 0; three = true; s = "die"; - - SerializerBinary ar2("hello.dat", true); - ar2 >> one; - ar2 >> two; - ar2 >> three; - ar2 >> s; - - printf("we got %d - %f - %s - \"%s\"\n", one, two, (three ? "true":"false"), s.getString() ); - return 0; -} diff --git a/src/tests/serializetext.cpp b/src/tests/serializetext.cpp deleted file mode 100644 index f6be7d3..0000000 --- a/src/tests/serializetext.cpp +++ /dev/null @@ -1,28 +0,0 @@ -#include "serializertext.h" -#include "staticstring.h" -#include <iostream> - -int main() -{ - StaticString s("You're a dog!!"); - SerializerText ar("hello.dat", false); - - ar << 4 << 3.993 << true << s; - - ar.close(); - - int one=0;float two=0.0;bool three=false; s = ""; - - SerializerText ar2("hello.dat", true); - - ar2 >> one; - ar2 >> two; - ar2 >> three; - ar2 >> s; - - //printf("out: %d, %f, %s, \"%s\"\n", one, two, (three ? "true" : "false"), s.getString()); - std::cout << one << ", " << two << ", " << three << ", " << s.getString() << "\n"; - - return 0; -} - diff --git a/src/tests/sha1.cpp b/src/tests/sha1.cpp deleted file mode 100644 index df3113c..0000000 --- a/src/tests/sha1.cpp +++ /dev/null @@ -1,44 +0,0 @@ -#include "sha1.h" -#include "sfile.h" - -#define BS 1024 - -int main( int argc, char *argv[] ) -{ - argc--; argv++; - - if( argc == 0 ) - { - printf("Provide a filename.\n"); - return 0; - } - - char buf[BS]; - - Sha1 s; - SFile fin( *argv, "rb" ); - for(;;) - { - int nRead = fin.read( buf, BS ); - if( nRead == 0 ) - break; - - s.update( buf, nRead ); - if( nRead < BS ) - break; - } - - unsigned char *dig = s.getDigest(); - - char val[]={"0123456789ABCDEF"}; - - for( int j = 0; j < 20; j++ ) - { - putchar( val[dig[j]>>4] ); - putchar( val[dig[j]&0x0F] ); - } - putchar('\n'); - - delete[] dig; -} - diff --git a/src/tests/sptr.cpp b/src/tests/sptr.cpp deleted file mode 100644 index 38d3675..0000000 --- a/src/tests/sptr.cpp +++ /dev/null @@ -1,55 +0,0 @@ -#include <stdio.h> -#include "sptr.h" - -class Annoy -{ -public: - Annoy() : nCnt( 0 ) - { - printf("Created.\n"); - } - - ~Annoy() - { - printf("Destroyed.\n"); - } - - void go() - { - printf("%d: I'm annoying.\n", ++nCnt); - } - - int nCnt; -}; - -void beAnnoying( SPtr<Annoy> bob ) -{ - printf("bob-Count: %d\n", bob.count() ); - bob->go(); -} - -int main() -{ - SPtr<Annoy> pt( new Annoy ); - printf("Count: %d\n", pt.count() ); - pt->go(); - - { - SPtr<Annoy> pt2 = pt; - printf("Count: %d\n", pt2.count() ); - - pt2->go(); - - { - SPtr<Annoy> pt3( pt2 ); - printf("Count: %d\n", pt3.count() ); - - pt3->go(); - - beAnnoying( pt3 ); - } - printf("Count: %d\n", pt.count() ); - } - printf("Count: %d\n", pt.count() ); -} - diff --git a/src/tests/srvstress.cpp b/src/tests/srvstress.cpp deleted file mode 100644 index d9a9a1c..0000000 --- a/src/tests/srvstress.cpp +++ /dev/null @@ -1,91 +0,0 @@ -#include "connectionmanager.h" -#include "programlink.h" -#include "linkedlist.h" -#include "protocol.h" - -class StressProtocol : public Protocol -{ -public: - bool onNewData() - { - switch( getConnection()->getInput()[0] ) - { - case 'd': - throw "Hello"; - break; - - case 'w': - getConnection()->appendOutput("Hello"); - break; - }; - - return true; - } - - bool onNewConnection() - { - return true; - } -}; - -class StressMonitor : public ConnectionMonitor, public ProgramLink -{ -public: - bool init() - { - return true; - } - - bool deInit() - { - return true; - } - - bool timeSlice() - { - return true; - } - - bool onNewConnection( Connection *pCon, int nPort ) - { - StressProtocol *sp = new StressProtocol(); - pCon->setProtocol( sp ); - - printf(" sys: New connection: socket(%d), port(%d)\n", - pCon->getSocket(), nPort ); - - return true; - } - - bool onClosedConnection( Connection *pCon ) - { - printf(" sys: Closed connection: socket(%d)\n", - pCon->getSocket() ); - - return true; - } - - LinkMessage *processIRM( LinkMessage *pMsg ) - { - return NULL; - } -}; - -int main() -{ - printf("Starting server...\n"); - - ConnectionManager srv; - StressMonitor telnet; - - srv.setConnectionMonitor( &telnet ); - - srv.startServer( 4001 ); - - for(;;) - { - srv.scanConnections( 5000, false ); - } - - return 0; -} diff --git a/src/tests/strhash.cpp b/src/tests/strhash.cpp deleted file mode 100644 index f6528ca..0000000 --- a/src/tests/strhash.cpp +++ /dev/null @@ -1,12 +0,0 @@ -#include <stdio.h> -#include "hashfunctionstring.h" - -int main( int argc, char *argv[] ) -{ - HashFunctionString h; - - printf("\"%s\": %lu\n", argv[1], h.hash( argv[1] ) ); - - return 0; -} - diff --git a/src/tests/teltest/main.cpp b/src/tests/teltest/main.cpp deleted file mode 100644 index 5d3ec26..0000000 --- a/src/tests/teltest/main.cpp +++ /dev/null @@ -1,21 +0,0 @@ -#include "connectionmanager.h" -#include "telnetmonitor.h" - -int main() -{ - printf("Starting server...\n"); - - ConnectionManager srv; - TelnetMonitor telnet; - - srv.setConnectionMonitor( &telnet ); - - srv.startServer( 4001 ); - - for(;;) - { - srv.scanConnections( 5000, false ); - } - - return 0; -} diff --git a/src/tests/teltest/telnetmonitor.cpp b/src/tests/teltest/telnetmonitor.cpp deleted file mode 100644 index 65954eb..0000000 --- a/src/tests/teltest/telnetmonitor.cpp +++ /dev/null @@ -1,54 +0,0 @@ -#include "telnetmonitor.h" -#include "protocoltelnet.h" -#include <sys/stat.h> - -TelnetMonitor::TelnetMonitor() -{ -} - -TelnetMonitor::~TelnetMonitor() -{ -} - -bool TelnetMonitor::init() -{ - return true; -} - -bool TelnetMonitor::deInit() -{ - return true; -} - -bool TelnetMonitor::timeSlice() -{ - for( int j = 0; j < lCon.getSize(); j++ ) - { - if( ((Connection *)lCon[j])->hasInput() ) - { - printf("%s\n", ((Connection *)lCon[j])->getInput() ); - } - } - return true; -} - -LinkMessage* TelnetMonitor::processIRM( LinkMessage *pMsg ) -{ - return NULL; -} - -bool TelnetMonitor::onNewConnection( Connection *pCon, int nPort ) -{ - ProtocolTelnet *pt = new ProtocolTelnet(); - pCon->setProtocol( pt ); - - lCon.append( pt ); - - return true; -} - -bool TelnetMonitor::onClosedConnection( Connection *pCon ) -{ - return true; -} - diff --git a/src/tests/teltest/telnetmonitor.h b/src/tests/teltest/telnetmonitor.h deleted file mode 100644 index ba5761e..0000000 --- a/src/tests/teltest/telnetmonitor.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef HTTPCONNECTIONMONITOR_H -#define HTTPCONNECTIONMONITOR_H - -#include "connectionmonitor.h" -#include "programlink.h" -#include "linkedlist.h" - -class TelnetMonitor : public ConnectionMonitor, public ProgramLink -{ -public: - TelnetMonitor(); - ~TelnetMonitor(); - - bool init(); - bool deInit(); - bool timeSlice(); - LinkMessage* processIRM( LinkMessage *pMsgIn ); - - bool onNewConnection( Connection *pCon, int nPort ); - bool onClosedConnection( Connection *pCon ); - -private: - LinkedList lCon; -}; - -#endif diff --git a/src/tests/xmlreadtest.cpp b/src/tests/xmlreadtest.cpp deleted file mode 100644 index d061810..0000000 --- a/src/tests/xmlreadtest.cpp +++ /dev/null @@ -1,29 +0,0 @@ -#include "xmlfilereader.h" -#include "xmlstringreader.h" -#include "xmlfilewriter.h" - -int main( int argc, char *argv[] ) -{ - if( argc < 4 ) - { - printf("Usage: %s f <file in> <file out>\n", argv[0] ); - printf(" %s s <xml string> <file out>\n\n", argv[0] ); - return 0; - } - - if( argv[1][0] == 'f' ) - { - XmlFileReader r( argv[2], true ); -// XmlFileWriter w( argv[3], "\t", r.detatchRoot() ); -// w.write(); - } - else if( argv[1][0] == 's' ) - { - XmlStringReader r( argv[2], true ); - XmlFileWriter w(stdout, "\t", r.detatchRoot() ); - w.write(); - } - - return 0; -} - diff --git a/src/tests/xmlrepltest.cpp b/src/tests/xmlrepltest.cpp deleted file mode 100644 index 9667705..0000000 --- a/src/tests/xmlrepltest.cpp +++ /dev/null @@ -1,31 +0,0 @@ -#include "xmlwriter.h" - -int main() -{ - printf("Testing Xml Replacement...\n"); - XmlDocument w; - - w.addNode("text"); - w.setContent("this text is before the node. "); - w.addNode("keepme", "This one we keep...", true ); - w.setContent("this text is after."); - w.addNode("deleteme", "This one we don't...", true ); - w.setContent("this is last..." ); - w.closeNode(); - - //XmlWriter::writeNode( stdout, w.getRoot(), 0, NULL ); - - printf("\n\n"); - - //XmlNode *xNode = w.getRoot()->detatchNode( 1 ); - - //XmlWriter::writeNode( stdout, w.getRoot(), 0, NULL ); - - printf("\n\n"); - - //XmlWriter::writeNode( stdout, xNode, 0, NULL ); - - printf("\n\n"); - - return 0; -} diff --git a/src/tests/xmlwritetest.cpp b/src/tests/xmlwritetest.cpp deleted file mode 100644 index a22d19d..0000000 --- a/src/tests/xmlwritetest.cpp +++ /dev/null @@ -1,48 +0,0 @@ -#include "xmlfilewriter.h" -#include "xmlstringwriter.h" -#include "xmlstringreader.h" - -void fillItIn( XmlWriter &w ) -{ - w.addNode("thinglist"); - - w.addNode("thing"); - w.addProperty("type", " ±î´<M-F6><M-F6>³¸®°êòì¯"); - - w.addNode("id", "Klophin²³±¹¸·µ´äêíëã Staff", true ); - w.addNode("name", "Klophin Staff", true ); - w.addNode("durability", "0.01", true ); - w.addNode("size", "0.1", true ); - - w.addNode("config"); - w.addNode("damage", "3d6+4", true ); - w.addNode("class", "melee", true ); - w.addNode("type", "bludgeon", true ); - w.addNode("damagedesc", "club/clubs", true ); - w.closeNode(); - - w.closeNode(); - - w.closeNode(); -} - -int main() -{ - printf("Testing XmlWriter...\n"); - - //XmlStringReader *xsr = new XmlStringReader("<stuff/>"); - - //printf("%08X\n%08X\n%08X\n", xsr, (XmlReader *)xsr, (XmlDocument *)xsr ); - - //delete (XmlDocument *)xsr; - XmlFileWriter wf("test.xml", "\t"); - - fillItIn( wf ); - - XmlStringWriter ws("\t"); - fillItIn( ws ); - - printf("Now the string version:\n\n%s\n", ws.getString().c_str() ); - - return 0; -} diff --git a/src/tokenstring.cpp b/src/tokenstring.cpp deleted file mode 100644 index e57ba69..0000000 --- a/src/tokenstring.cpp +++ /dev/null @@ -1,163 +0,0 @@ -#include "tokenstring.h" -#include <string.h> - -TokenString::TokenString( const char *lpNewTokenString ) -{ - lpTokenString = NULL; - if( lpNewTokenString ) - { - parseLine( lpNewTokenString ); - } -} - -TokenString::~TokenString() -{ - delete[] lpTokenString; - for( int j = 0; j < lToken.getSize(); j++ ) - { - delete[] (((Token *)lToken[j])->lpToken); - delete ((Token *)lToken[j]); - } -} - -void TokenString::parseLine( const char *lpNewTokenString ) -{ - if( lpTokenString != NULL ) - { - delete[] lpTokenString; - lpTokenString = NULL; - for( int j = 0; j < lToken.getSize(); j++ ) - { - delete[] (((Token *)lToken[j])->lpToken); - delete ((Token *)lToken[j]); - } - lToken.empty(); - } - if( lpNewTokenString == NULL ) - { - lpTokenString = new char[1]; - lpTokenString[0] = '\0'; - lToken.setSize(0); - return; - } - // First order of business, make an internal copy so someone can get it - // if they want to. - int nLen = strlen(lpNewTokenString); - lpTokenString = new char[nLen+1]; - strcpy( lpTokenString, lpNewTokenString ); - - // Now we do a preliminary parse. This could be effected by later - // editing and aliasing, but we'll see... - int nTkStart, nTkEnd; - int mode=0; // 0 = startSearch, 1=endSearch - for( int j = 0; j <= nLen; j++ ) - { - if( mode == 0 ) - { - if( lpTokenString[j] != ' ' && - lpTokenString[j] != '\t' ) - { - nTkStart = j; - mode = 1; - } - } - else - { - if( lpTokenString[j] == ' ' || - lpTokenString[j] == '\t' || - lpTokenString[j] == '\0' ) - { - nTkEnd = j-1; - mode = 0; - - appendToken( nTkStart, nTkEnd ); - } - } - } -} - -void TokenString::appendToken( int nStart, int nEnd ) -{ - Token *pToken = new Token; - pToken->lpOrig = &lpTokenString[nStart]; - - // nStart and nEnd are inclusive, we must add two for the end, and the null - pToken->lpToken = new char[nEnd-nStart+2]; - memcpy( pToken->lpToken, &lpTokenString[nStart], nEnd-nStart+1 ); - pToken->lpToken[nEnd-nStart+1] = '\0'; - -// printf("%s\n", pToken->lpToken ); - lToken.append( pToken ); -} - -void TokenString::insertToken( int nStart, int nEnd, char *lpOldOrig, const char *lpNewToken, int nIndex ) -{ - Token *pToken = new Token; - pToken->lpOrig = lpOldOrig; - - // nStart and nEnd are inclusive, we must add two for the end, and the null - pToken->lpToken = new char[nEnd-nStart+2]; - memcpy( pToken->lpToken, &lpNewToken[nStart], nEnd-nStart+1 ); - pToken->lpToken[nEnd-nStart+1] = '\0'; - - lToken.insertBefore( pToken, nIndex ); -} - -int TokenString::getNumTokens() -{ - return lToken.getSize(); -} - -char *TokenString::getToken( int nIndex ) -{ - if( nIndex >= lToken.getSize() ) return NULL; - return (char *)(((Token *)lToken[nIndex])->lpToken); -} - -char *TokenString::getTokenString( int nIndex ) -{ - if( nIndex >= lToken.getSize() ) return NULL; - return (char *)(((Token *)lToken[nIndex])->lpOrig); -} - -void TokenString::expandTokenTo( int nIndex, char *lpNewToken ) -{ - // First, we delete the token at nIndex, then we keep inserting - // at that position... - // We also have to remember the index to the original string, - // since most of what we're expanding to won't be in the origingal - // we need to keep these indexes updated in order to make other parts - // of the system happy. - char *lpOldOrig = ((Token *)lToken[nIndex])->lpOrig; - delete[] ((Token *)lToken[nIndex])->lpToken; - delete ((Token *)lToken[nIndex]); - lToken.deleteAt( nIndex ); - - // We'll do this just like we did above, but instead we'll - // do tricky things when we find tokens... - int nLen = strlen(lpNewToken); - int nTkStart, nTkEnd, nNewIndex=nIndex; - int mode=0; // 0 = startSearch, 1=endSearch - for( int j = 0; j <= nLen; j++ ) - { - if( mode == 0 ) - { - if( lpNewToken[j] != ' ' && lpNewToken[j] != '\t' ) - { - nTkStart = j; - mode = 1; - } - } - else - { - if( lpNewToken[j] == ' ' || lpNewToken[j] == '\t' || lpNewToken[j] == '\0' ) - { - nTkEnd = j-1; - mode = 0; - - insertToken( nTkStart, nTkEnd, lpOldOrig, lpNewToken, nNewIndex ); - nNewIndex++; - } - } - } -} diff --git a/src/tokenstring.h b/src/tokenstring.h deleted file mode 100644 index 42f7309..0000000 --- a/src/tokenstring.h +++ /dev/null @@ -1,114 +0,0 @@ -#ifndef TOKENSTRING_H -#define TOKENSTRING_H - -#include "linkedlist.h" - -/** A single tokenized command line. Contains all information necesarry to - * nicely access a stand-alone command line and to perform alias expansion - * inside of that command line. - * When expanding a token, the original command line is left intact, so any - * command usng a command line verbatum (getTokenString not getToken) will get - * the original, and not the expanded version. - * Since indexing into the original command line is also done by token, it - * means that using getTokenString( 0 ) will not always get you the first - * character of the command line, it will get you the first non-whitespace - * character. - * Furthermore, when expanding the expantion string is tokenized as well, - * but since the original string is unchanged, all tokens that expand any - * given index will all retain the same index into the original command line. - *@todo Update this to allow it to break on different types of token - * delimiters. - *@author Mike Buland - */ -class TokenString{ -public: - /** Automatically call parseLine when created. - *@param lpNewTokenString The command line to tokenize - *@author Mike Buland - */ - TokenString( const char *lpNewTokenString=NULL ); - virtual ~TokenString(); - - /** Performs a tokenizing parse on the given command line, setting it as - * the internal command line for all future tokenizing (excluding - * expansion) - *@param lpNewTokenString The new command line to set to this object. - *@author Mike Buland - */ - void parseLine( const char *lpNewTokenString ); - - /** Appends a token to the list of available tokens. This references the - * internal pointer to the command line, so no token string must be - * specified. - *@param nStart The first character of the token to insert. - *@param nEnd The last character of the token to insert. - *@author Mike Buland - */ - void appendToken( int nStart, int nEnd ); - - /** Gets the number of tokens. This is particularly useful post-aliasing - * since the number of tokens may not match what is percieved from the - * original command line. - *@returns The number of available tokens. - *@author Mike Buland - */ - int getNumTokens(); - - /** Gets a processed token specified by index. - *@param nIndex The index of the token to retrieve. - *@returns A pointer to the requested token. Please note that these tokens - * may not match the original command line. - *@author Mike Buland - */ - char *getToken( int nIndex ); - - /** Gets the original command line based on tokens. Use this if you want - * to perform your own processing on parts of the command line, without - * resorting to tokens. - * The first character in the returned string will always be - * non-whitespace. - *@param nIndex The index of the token to start at, zero gets you the whole - * command line. - *@returns A pointer to the internal original command line string, starting - * at the position of the first non-whitespace character of the token - * specified. - *@author Mike Buland - */ - char *getTokenString( int nIndex=0 ); - - /** Expands a token, replacing it with the string lpNewToken, but - * processing the new string for tokens before performing the replacement - *@param nIndex Which token should be replaced. - *@param lpNewToken The string to replace the token with. - *@author Mike Buland - */ - void expandTokenTo( int nIndex, char *lpNewToken ); - - /** Inserts a token at any position in the command line. This does not - * effect the original command line. - *@param nStart The start of the token in the string lpNewToken. (inclusive) - *@param nEnd The end of the token in the string lpToken. (inclusive) - *@param lpOldOrig The pointer to the position in the orginal command - * line where this new token should point. - *@param lpNewToken The string containing the new token. May contain more - * than just one token. - *@param nIndex The position to insert the token to. - *@author Mike Buland - */ - void insertToken( int nStart, int nEnd, char *lpOldOrig, const char *lpNewToken, int nIndex ); - -private: - char *lpTokenString; /**< The original text that this string came from */ - LinkedList lToken; /**< The list of tokens. */ - - /** - * A single token within the token string. - */ - typedef struct Token - { - char *lpOrig; /**< This is just a pointer back to lpTokenString */ - char *lpToken; /**< This is really a whole token */ - } Token; -}; - -#endif diff --git a/src/tqsort.h b/src/tqsort.h deleted file mode 100644 index c836b4f..0000000 --- a/src/tqsort.h +++ /dev/null @@ -1,207 +0,0 @@ -#ifndef T_QSORT_H -#define T_QSORT_H - -#define _QSORT_SWAP(a, b, t) ((void)((t = *a), (*a = *b), (*b = t))) - -/* Discontinue quicksort algorithm when partition gets below this size. - This particular magic number was chosen to work best on a Sun 4/260. */ -#define _QSORT_MAX_THRESH 4 - -/* Stack node declarations used to store unfulfilled partition obligations - * (inlined in QSORT). -typedef struct { - QSORT_TYPE *_lo, *_hi; -} qsort_stack_node; - */ - -/* The next 4 #defines implement a very fast in-line stack abstraction. */ -/* The stack needs log (total_elements) entries (we could even subtract - log(MAX_THRESH)). Since total_elements has type unsigned, we get as - upper bound for log (total_elements): - bits per byte (CHAR_BIT) * sizeof(unsigned). */ -#define _QSORT_STACK_SIZE (8 * sizeof(unsigned)) -#define _QSORT_PUSH(top, low, high) \ - (((top->_lo = (low)), (top->_hi = (high)), ++top)) -#define _QSORT_POP(low, high, top) \ - ((--top, (low = top->_lo), (high = top->_hi))) -#define _QSORT_STACK_NOT_EMPTY (_stack < _top) - - -/* Order size using quicksort. This implementation incorporates - four optimizations discussed in Sedgewick: - - 1. Non-recursive, using an explicit stack of pointer that store the - next array partition to sort. To save time, this maximum amount - of space required to store an array of SIZE_MAX is allocated on the - stack. Assuming a 32-bit (64 bit) integer for size_t, this needs - only 32 * sizeof(stack_node) == 256 bytes (for 64 bit: 1024 bytes). - Pretty cheap, actually. - - 2. Chose the pivot element using a median-of-three decision tree. - This reduces the probability of selecting a bad pivot value and - eliminates certain extraneous comparisons. - - 3. Only quicksorts TOTAL_ELEMS / MAX_THRESH partitions, leaving - insertion sort to order the MAX_THRESH items within each partition. - This is a big win, since insertion sort is faster for small, mostly - sorted array segments. - - 4. The larger of the two sub-partitions is always pushed onto the - stack first, with the algorithm then concentrating on the - smaller partition. This *guarantees* no more than log (total_elems) - stack size is needed (actually O(1) in this case)! */ - -/* The main code starts here... */ - -template<typename QSORT_TYPE, typename QSORT_LTT, typename CST> -void tqsort( QSORT_TYPE *QSORT_BASE, int QSORT_NELT ) -{ - QSORT_LTT QSORT_LT; - QSORT_TYPE *const _base = (QSORT_BASE); - const unsigned _elems = (QSORT_NELT); - QSORT_TYPE _hold; - - /* Don't declare two variables of type QSORT_TYPE in a single - * statement: eg `TYPE a, b;', in case if TYPE is a pointer, - * expands to `type* a, b;' wich isn't what we want. - */ - - if (_elems > _QSORT_MAX_THRESH) { - QSORT_TYPE *_lo = _base; - QSORT_TYPE *_hi = _lo + _elems - 1; - struct { - QSORT_TYPE *_hi; QSORT_TYPE *_lo; - } _stack[_QSORT_STACK_SIZE], *_top = _stack + 1; - - while (_QSORT_STACK_NOT_EMPTY) { - QSORT_TYPE *_left_ptr; QSORT_TYPE *_right_ptr; - - /* Select median value from among LO, MID, and HI. Rearrange - LO and HI so the three values are sorted. This lowers the - probability of picking a pathological pivot value and - skips a comparison for both the LEFT_PTR and RIGHT_PTR in - the while loops. */ - - QSORT_TYPE *_mid = _lo + ((_hi - _lo) >> 1); - - if (QSORT_LT ((CST)(_mid), (CST)(_lo))) - _QSORT_SWAP (_mid, _lo, _hold); - if (QSORT_LT ((CST)(_hi), (CST)(_mid))) - _QSORT_SWAP (_mid, _hi, _hold); - else - goto _jump_over; - if (QSORT_LT ((CST)(_mid), (CST)(_lo))) - _QSORT_SWAP (_mid, _lo, _hold); - _jump_over:; - - _left_ptr = _lo + 1; - _right_ptr = _hi - 1; - - /* Here's the famous ``collapse the walls'' section of quicksort. - Gotta like those tight inner loops! They are the main reason - that this algorithm runs much faster than others. */ - do { - while (QSORT_LT ((CST)(_left_ptr), (CST)(_mid))) - ++_left_ptr; - - while (QSORT_LT ((CST)(_mid), (CST)(_right_ptr))) - --_right_ptr; - - if (_left_ptr < _right_ptr) { - _QSORT_SWAP (_left_ptr, _right_ptr, _hold); - if (_mid == _left_ptr) - _mid = _right_ptr; - else if (_mid == _right_ptr) - _mid = _left_ptr; - ++_left_ptr; - --_right_ptr; - } - else if (_left_ptr == _right_ptr) { - ++_left_ptr; - --_right_ptr; - break; - } - } while (_left_ptr <= _right_ptr); - - /* Set up pointers for next iteration. First determine whether - left and right partitions are below the threshold size. If so, - ignore one or both. Otherwise, push the larger partition's - bounds on the stack and continue sorting the smaller one. */ - - if (_right_ptr - _lo <= _QSORT_MAX_THRESH) { - if (_hi - _left_ptr <= _QSORT_MAX_THRESH) - /* Ignore both small partitions. */ - _QSORT_POP (_lo, _hi, _top); - else - /* Ignore small left partition. */ - _lo = _left_ptr; - } - else if (_hi - _left_ptr <= _QSORT_MAX_THRESH) - /* Ignore small right partition. */ - _hi = _right_ptr; - else if (_right_ptr - _lo > _hi - _left_ptr) { - /* Push larger left partition indices. */ - _QSORT_PUSH (_top, _lo, _right_ptr); - _lo = _left_ptr; - } - else { - /* Push larger right partition indices. */ - _QSORT_PUSH (_top, _left_ptr, _hi); - _hi = _right_ptr; - } - } - } - - /* Once the BASE array is partially sorted by quicksort the rest - is completely sorted using insertion sort, since this is efficient - for partitions below MAX_THRESH size. BASE points to the - beginning of the array to sort, and END_PTR points at the very - last element in the array (*not* one beyond it!). */ - - { - QSORT_TYPE *const _end_ptr = _base + _elems - 1; - QSORT_TYPE *_tmp_ptr = _base; - register QSORT_TYPE *_run_ptr; - QSORT_TYPE *_thresh; - - _thresh = _base + _QSORT_MAX_THRESH; - if (_thresh > _end_ptr) - _thresh = _end_ptr; - - /* Find smallest element in first threshold and place it at the - array's beginning. This is the smallest array element, - and the operation speeds up insertion sort's inner loop. */ - - for (_run_ptr = _tmp_ptr + 1; _run_ptr <= _thresh; ++_run_ptr) - if (QSORT_LT ((CST)(_run_ptr), (CST)(_tmp_ptr))) - _tmp_ptr = _run_ptr; - - if (_tmp_ptr != _base) - _QSORT_SWAP (_tmp_ptr, _base, _hold); - - /* Insertion sort, running from left-hand-side - * up to right-hand-side. */ - - _run_ptr = _base + 1; - while (++_run_ptr <= _end_ptr) { - _tmp_ptr = _run_ptr - 1; - while (QSORT_LT ((CST)(_run_ptr), (CST)(_tmp_ptr))) - --_tmp_ptr; - - ++_tmp_ptr; - if (_tmp_ptr != _run_ptr) { - QSORT_TYPE *_trav = _run_ptr + 1; - while (--_trav >= _run_ptr) { - QSORT_TYPE *_hi; QSORT_TYPE *_lo; - _hold = *_trav; - - for (_hi = _lo = _trav; --_lo >= _tmp_ptr; _hi = _lo) - *_hi = *_lo; - *_hi = _hold; - } - } - } - } -} - -#endif diff --git a/src/unit/hashtable/hashtable.cpp b/src/unit/hashtable/hashtable.cpp deleted file mode 100644 index b2e1cf5..0000000 --- a/src/unit/hashtable/hashtable.cpp +++ /dev/null @@ -1,107 +0,0 @@ -#include <cstdlib> -#include <cstring> -#include <iostream> -#include <cpptest.h> -#include <string.h> -#include <set> -#include <map> - -#include "hashfunctionstring.h" -#include "hashfunctioncasestring.h" -#include "hashfunctionint.h" - -class HashFunctionSuite : public Test::Suite -{ -public: - HashFunctionSuite() - { - TEST_ADD( HashFunctionSuite::functionString ) - TEST_ADD( HashFunctionSuite::functionCaseString ) - TEST_ADD( HashFunctionSuite::functionInt ) - } - -private: - void functionStringWorker( HashFunction &hf, std::set<unsigned long> &sCodes, char *str, int nLevel, int nMax ) - { - for( char let = 'A'; let <= 'z'; let += 3 ) - { - str[nLevel+1] = '\0'; - str[nLevel] = let; - unsigned long x = hf.hash( str ); - TEST_ASSERT( sCodes.find( x ) == sCodes.end() ); - TEST_ASSERT( hf.cmpIDs( str, str ) ); - sCodes.insert( x ); - - if( nLevel < nMax ) - functionStringWorker( hf, sCodes, str, nLevel+1, nMax ); - } - } - - void functionString() - { - HashFunctionString hf; - char str[10]; - - std::set<unsigned long> sCodes; - - functionStringWorker( hf, sCodes, str, 0, 3 ); - } - - void functionCaseStringWorker( HashFunction &hf, std::map<unsigned long, char *> &sCodes, char *str, int nLevel, int nMax ) - { - for( char let = 'A'; let <= 'z'; let += 3 ) - { - str[nLevel+1] = '\0'; - str[nLevel] = let; - unsigned long x = hf.hash( str ); - std::map<unsigned long, char *>::iterator i = sCodes.find( x ); - if( i == sCodes.end() ) - { - sCodes[x] = strdup( str ); - } - else - { - TEST_ASSERT( strcasecmp( (*i).second, str ) == 0 ); - TEST_ASSERT( hf.cmpIDs( (*i).second, str ) == true ); - } - - if( nLevel < nMax ) - functionCaseStringWorker( hf, sCodes, str, nLevel+1, nMax ); - } - } - - void functionCaseString() - { - HashFunctionCaseString hf; - char str[10]; - - std::map<unsigned long, char *> sCodes; - - functionCaseStringWorker( hf, sCodes, str, 0, 3 ); - - std::map<unsigned long, char *>::iterator i; - for( i = sCodes.begin(); i != sCodes.end(); i++ ) - { - free( (*i).second ); - } - } - - void functionInt() - { - HashFunctionInt hf; - - for( long i = -100000; i <= 100000; i += 100 ) - { - TEST_ASSERT( ((long)hf.hash( (void *)i )) == i ); - TEST_ASSERT( ((long)hf.cmpIDs( (void *)i, (void *)i )) ); - } - } -}; - -int main( int argc, char *argv[] ) -{ - Test::TextOutput output( Test::TextOutput::Verbose ); - HashFunctionSuite ts; - return ts.run( output ) ? EXIT_SUCCESS : EXIT_FAILURE; -} - diff --git a/src/unit/xml/xml.cpp b/src/unit/xml/xml.cpp deleted file mode 100644 index e4d779c..0000000 --- a/src/unit/xml/xml.cpp +++ /dev/null @@ -1,59 +0,0 @@ -#include <cstdlib> -#include <cstring> -#include <iostream> -#include <cpptest.h> -#include <string.h> - -#include "xmlstringreader.h" -#include "xmlexception.h" - -class XmlCoreTestSuite : public Test::Suite -{ -public: - XmlCoreTestSuite() - { - TEST_ADD( XmlCoreTestSuite::badXml01 ) - TEST_ADD( XmlCoreTestSuite::badXml02 ) - TEST_ADD( XmlCoreTestSuite::badXml03 ) - - TEST_ADD( XmlCoreTestSuite::entityBuiltin01 ) - - TEST_ADD( XmlCoreTestSuite::entityDoc01 ) - } - -private: - void badXml01() - { - TEST_THROWS( XmlStringReader r("<hello></bye>"), XmlException & ); - } - - void badXml02() - { - TEST_THROWS( XmlStringReader r("<hello>"), XmlException & ); - } - - void badXml03() - { - TEST_THROWS( XmlStringReader r("<hello param=\"stuff?"), XmlException & ); - } - - void entityBuiltin01() - { - XmlStringReader r("<hello>><&'"</hello>"); - TEST_ASSERT( strcmp( r.getRoot()->getContent(), "><&\'\"" ) == 0 ); - } - - void entityDoc01() - { - XmlStringReader r("<!ENTITY name \"bob the man\"><hello>"&name;"</hello>"); - TEST_ASSERT( strcmp( r.getRoot()->getContent(), "\"bob the man\"" ) == 0 ); - } -}; - -int main( int argc, char *argv[] ) -{ - Test::TextOutput output( Test::TextOutput::Verbose ); - XmlCoreTestSuite ts; - return ts.run( output ) ? EXIT_SUCCESS : EXIT_FAILURE; -} - diff --git a/src/xmldocument.cpp b/src/xmldocument.cpp deleted file mode 100644 index d7867d5..0000000 --- a/src/xmldocument.cpp +++ /dev/null @@ -1,149 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> -#include "xmlwriter.h" - -XmlDocument::XmlDocument( XmlNode *pRoot ) -{ - this->pRoot = pRoot; - pCurrent = NULL; - bCompleted = (pRoot!=NULL); -} - -XmlDocument::~XmlDocument() -{ - if( pRoot ) - { - delete pRoot; - } -} - -void XmlDocument::addNode( const char *sName, const char *sContent, bool bClose ) -{ - if( pRoot == NULL ) - { - // This is the first node, so ignore position and just insert it. - pCurrent = pRoot = new XmlNode( sName, NULL, sContent ); - } - else - { - pCurrent = pCurrent->addChild( sName, sContent ); - } - - if( bClose ) - { - closeNode(); - } -} - -void XmlDocument::setName( const char *sName ) -{ - pCurrent->setName( sName ); -} - -bool XmlDocument::isCompleted() -{ - return bCompleted; -} - -XmlNode *XmlDocument::getRoot() -{ - return pRoot; -} - -XmlNode *XmlDocument::detatchRoot() -{ - XmlNode *pTemp = pRoot; - pRoot = NULL; - return pTemp; -} - -XmlNode *XmlDocument::getCurrent() -{ - return pCurrent; -} - -void XmlDocument::closeNode() -{ - if( pCurrent != NULL ) - { - pCurrent = pCurrent->getParent(); - - if( pCurrent == NULL ) - { - bCompleted = true; - } - } -} - -void XmlDocument::addProperty( const char *sName, const char *sValue ) -{ - if( pCurrent ) - { - pCurrent->addProperty( sName, sValue ); - } -} - -void XmlDocument::addProperty( const char *sName, const unsigned char nValue ) -{ - char buf[12]; - sprintf( buf, "%hhi", nValue ); - addProperty( sName, buf ); -} - -void XmlDocument::addProperty( const char *sName, const char nValue ) -{ - char buf[12]; - sprintf( buf, "%hhi", nValue ); - addProperty( sName, buf ); -} - -void XmlDocument::addProperty( const char *sName, const unsigned short nValue ) -{ - char buf[12]; - sprintf( buf, "%hi", nValue ); - addProperty( sName, buf ); -} - -void XmlDocument::addProperty( const char *sName, const short nValue ) -{ - char buf[12]; - sprintf( buf, "%hi", nValue ); - addProperty( sName, buf ); -} - -void XmlDocument::addProperty( const char *sName, const int nValue ) -{ - char buf[12]; - sprintf( buf, "%d", nValue ); - addProperty( sName, buf ); -} - -void XmlDocument::addProperty( const char *sName, const unsigned long nValue ) -{ - char buf[12]; - sprintf( buf, "%li", nValue ); - addProperty( sName, buf ); -} - -void XmlDocument::addProperty( const char *sName, const long nValue ) -{ - char buf[12]; - sprintf( buf, "%li", nValue ); - addProperty( sName, buf ); -} - -void XmlDocument::addProperty( const char *sName, const double dValue ) -{ - char buf[40]; - sprintf( buf, "%f", dValue ); - addProperty( sName, buf ); -} - -void XmlDocument::setContent( const char *sContent ) -{ - if( pCurrent ) - { - pCurrent->setContent( sContent ); - } -} - diff --git a/src/xmldocument.h b/src/xmldocument.h deleted file mode 100644 index 6671c41..0000000 --- a/src/xmldocument.h +++ /dev/null @@ -1,171 +0,0 @@ -#ifndef XMLDOCUMENT -#define XMLDOCUMENT - -#include "xmlnode.h" - -/** - * Keeps track of an easily managed set of XmlNode information. Allows simple - * operations for logical writing to and reading from XML structures. Using - * already formed structures is simply done through the XmlNode structures, - * and the getRoot function here. Creation is performed through a simple set - * of operations that creates the data in a stream type format. - *@author Mike Buland - */ -class XmlDocument -{ -public: - /** - * Construct either a blank XmlDocuemnt or construct a document around an - * existing XmlNode. Be careful, once an XmlNode is passed into a document - * the document takes over ownership and will delete it when the XmlDocument - * is deleted. - *@param pRoot The XmlNode to use as the root of this document, or NULL if - * you want to start a new document. - */ - XmlDocument( XmlNode *pRoot=NULL ); - - /** - * Destroy all contained nodes. - */ - virtual ~XmlDocument(); - - /** - * Add a new node to the document. The new node is appended to the end of - * the current context, i.e. XmlNode, and the new node, provided it isn't - * close as part of this operation, will become the current context. - *@param sName The name of the new node to add. - *@param sContent A content string to be placed inside of the new node. - *@param bClose Set this to true to close the node immediately after adding - * the node and setting the content and name. If this is set to true the - * node is appended, but the context node doesn't change. - */ - void addNode( const char *sName=NULL, const char *sContent=NULL, bool bClose=false ); - - /** - * Set the name of the current node context. - *@param sName The new name of the node. - */ - void setName( const char *sName ); - - /** - * Close the current node context. This will move the current context to - * the parent node of the former current node. If the current node was the - * root then the "completed" flag is set and no more operations are allowed. - */ - void closeNode(); - - /** - * Change the content of the current node at the current position between - * nodes. - *@param sContent The new content of the current node. - */ - void setContent( const char *sContent ); - - /** - * Add a named property to the current context node. - *@param sName The name of the property to add. - *@param sValue The string value of the property. - */ - void addProperty( const char *sName, const char *sValue ); - - /** - * Add a named property to the current context node, converting the - * numerical parameter to text using standrd printf style conversion. - *@param sName The name of the property to add. - *@param nValue The numerical value to add. - */ - void addProperty( const char *sName, const unsigned char nValue ); - - /** - * Add a named property to the current context node, converting the - * numerical parameter to text using standrd printf style conversion. - *@param sName The name of the property to add. - *@param nValue The numerical value to add. - */ - void addProperty( const char *sName, const char nValue ); - - /** - * Add a named property to the current context node, converting the - * numerical parameter to text using standrd printf style conversion. - *@param sName The name of the property to add. - *@param nValue The numerical value to add. - */ - void addProperty( const char *sName, const unsigned short nValue ); - - /** - * Add a named property to the current context node, converting the - * numerical parameter to text using standrd printf style conversion. - *@param sName The name of the property to add. - *@param nValue The numerical value to add. - */ - void addProperty( const char *sName, const short nValue ); - - /** - * Add a named property to the current context node, converting the - * numerical parameter to text using standrd printf style conversion. - *@param sName The name of the property to add. - *@param nValue The numerical value to add. - */ - void addProperty( const char *sName, const unsigned long nValue ); - - /** - * Add a named property to the current context node, converting the - * numerical parameter to text using standrd printf style conversion. - *@param sName The name of the property to add. - *@param nValue The numerical value to add. - */ - void addProperty( const char *sName, const long nValue ); - - /** - * Add a named property to the current context node, converting the - * numerical parameter to text using standrd printf style conversion. - *@param sName The name of the property to add. - *@param nValue The numerical value to add. - */ - void addProperty( const char *sName, const int nValue ); - - /** - * Add a named property to the current context node, converting the - * numerical parameter to text using standrd printf style conversion. - *@param sName The name of the property to add. - *@param dValue The numerical value to add. - */ - void addProperty( const char *sName, const double dValue ); - - /** - * The XmlDocuemnt is considered completed if the root node has been closed. - * Once an XmlDocument has been completed, you can no longer perform - * operations on it. - *@return True if completed, false if still in progress. - */ - bool isCompleted(); - - /** - * Get a pointer to the root object of this XmlDocument. - *@returns A pointer to an internally owned XmlNode. Do not delete this - * XmlNode. - */ - XmlNode *getRoot(); - - /** - * Get a pointer to the root object of this XmlDocument, and remove the - * ownership from this object. - *@returns A pointer to an internally owned XmlNode. Do not delete this - * XmlNode. - */ - XmlNode *detatchRoot(); - - /** - * Get the current context node, which could be the same as the root node. - *@returns A pointer to an internally owned XmlNode. Do not delete this - * XmlNode. - */ - XmlNode *getCurrent(); - -private: - XmlNode *pRoot; /**< The root node. */ - XmlNode *pCurrent; /**< The current node. */ - bool bCompleted; /**< Is it completed? */ -}; - -#endif diff --git a/src/xmlfilereader.cpp b/src/xmlfilereader.cpp deleted file mode 100644 index ed674a8..0000000 --- a/src/xmlfilereader.cpp +++ /dev/null @@ -1,58 +0,0 @@ -#include "xmlfilereader.h" -#include "exceptions.h" -#include <string.h> - -XmlFileReader::XmlFileReader( const char *sFile, bool bStrip ) - : XmlReader( bStrip ) -{ - fh = fopen( sFile, "rt" ); - - if( fh == NULL ) - { - throw XmlException("Couldn't open file: %s", sFile ); - //nError = 1; - } - else - { - buildDoc(); - } -} - -XmlFileReader::~XmlFileReader() -{ -} - -char XmlFileReader::getChar( int nIndex ) -{ - // Make sure we always have a little data left in the buffer - if( fbDataIn.getLength() <= nIndex+1 && fh ) - { - int nBytes = fbDataIn.getCapacity()-1; - char *buf = new char[nBytes]; - int nRead = fread( buf, 1, nBytes, fh ); - fbDataIn.appendData( buf, nRead ); - delete[] buf; - - if( nRead < nBytes ) - { - fclose( fh ); - fh = NULL; - } - } - if( fbDataIn.getLength() >= nIndex+1 ) - { - return fbDataIn.getData()[nIndex]; - } - else - { - throw XmlException("End of XML stream read."); - } -} - -void XmlFileReader::usedChar( int nAmnt ) -{ - if( fbDataIn.getLength()-nAmnt >= 0 ) - { - fbDataIn.usedData( nAmnt ); - } -} diff --git a/src/xmlfilereader.h b/src/xmlfilereader.h deleted file mode 100644 index e3e02c2..0000000 --- a/src/xmlfilereader.h +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef XMLFILEREADER -#define XMLFILEREADER - -#include <stdio.h> -#include "xmlreader.h" -#include "flexbuf.h" - -/** - * Takes care of reading in xml formatted data from a file. This could/should - * be made more arbitrary in the future so that we can read the data from any - * source. This is actually made quite simple already since all data read in - * is handled by one single helper function and then palced into a FlexBuf for - * easy access by the other functions. The FlexBuf also allows for block - * reading from disk, which improves speed by a noticable amount. - * <br> - * There are also some extra features implemented that allow you to break the - * standard XML reader specs and eliminate leading and trailing whitespace in - * all read content. This is useful in situations where you allow additional - * whitespace in the files to make them easily human readable. The resturned - * content will be NULL in sitautions where all content between nodes was - * stripped. - *@author Mike Buland - */ -class XmlFileReader : public XmlReader -{ -public: - /** - * Construct an XmlReader around an xml file on your file system. - *@param sFile The file to read. - *@param bStrip Set to true to strip out leading and trailing whitespace in - * node contents. - */ - XmlFileReader( const char *sFile, bool bStrip=false ); - - /** - * Destroy the reader and cleanup. - */ - virtual ~XmlFileReader(); - -private: - char getChar( int nIndex = 0 ); - void usedChar( int nAmnt = 1 ); - FILE *fh; /**< The file handle. */ - FlexBuf fbDataIn; /**< The input buffer. */ -}; - -#endif diff --git a/src/xmlfilewriter.cpp b/src/xmlfilewriter.cpp deleted file mode 100644 index 3c6fb41..0000000 --- a/src/xmlfilewriter.cpp +++ /dev/null @@ -1,28 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> -#include "xmlfilewriter.h" - -XmlFileWriter::XmlFileWriter( const char *sFileName, const char *sIndent, XmlNode *pRoot ) : - XmlWriter( sIndent, pRoot ) -{ - this->sFileName = sFileName; - fh = fopen( sFileName, "wt"); - fprintf( fh, "<?xml version=\"1.0\"?>\n"); -} - -XmlFileWriter::XmlFileWriter( FILE *fh, const char *sIndent, XmlNode *pRoot ) : - XmlWriter( sIndent, pRoot ), - fh( fh ) -{ -} - -XmlFileWriter::~XmlFileWriter() -{ - fclose( fh ); -} - -void XmlFileWriter::writeString( const char *sString ) -{ - fputs( sString, fh ); -} - diff --git a/src/xmlfilewriter.h b/src/xmlfilewriter.h deleted file mode 100644 index e328f96..0000000 --- a/src/xmlfilewriter.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef XML_FILE_WRITER -#define XML_FILE_WRITER - -#include "xmlnode.h" -#include "xmlwriter.h" - -/** - * Implements xml writing in the XML standard format. Also allows you to - * break that format and auto-indent your exported xml data for ease of - * reading. The auto-indenting will only be applied to sections that - * have no content of their own already. This means that except for - * whitespace all of your data will be preserved perfectly. - * You can create an XmlWriter object around a file, or access the static - * write function directly and just hand it a filename and a root XmlNode. - * When using an XmlWriter object the interface is identicle to that of - * the XmlDocument class, so reference that class for API info. However - * when the initial (or root) node is closed, and the document is finished - * the file will be created and written to automatically. The user can - * check to see if this is actually true by calling the isFinished - * function in the XmlDocument class. - *@author Mike Buland - */ -class XmlFileWriter : public XmlWriter -{ -public: - /** - * Construct a file writer around a given file. - *@param sFileName The file to create or overwrite and write XML into. - *@param sIndent The indent text to use, if any. - */ - XmlFileWriter( const char *sFileName, const char *sIndent=NULL, XmlNode *pRoot=NULL ); - XmlFileWriter( FILE *fh, const char *sIndent=NULL, XmlNode *pRoot=NULL ); - - /** - * Destroy the writer. - */ - virtual ~XmlFileWriter(); - -private: - void writeString( const char *sString ); - std::string sFileName; /**< The filename to write to. */ - FILE *fh; /**< The file handle to the open file. */ -}; - -#endif diff --git a/src/xmlnode.cpp b/src/xmlnode.cpp deleted file mode 100644 index b1ed9a9..0000000 --- a/src/xmlnode.cpp +++ /dev/null @@ -1,445 +0,0 @@ -#include "xmlnode.h" -#include "hashfunctionstring.h" - -XmlNode::XmlNode( const char *sName, XmlNode *pParent, const char *sContent ) : - hProperties( new HashFunctionString(), 53, false ), - hChildren( new HashFunctionString(), 53, true ) -{ - this->pParent = pParent; - if( sName != NULL ) - { - setName( sName ); - } - if( sContent != NULL ) - { - this->sPreContent = new std::string( sContent ); - } - else - { - this->sPreContent = NULL; - } - nCurContent = 0; -} - -XmlNode::~XmlNode() -{ - for( int j = 0; j < lChildren.getSize(); j++ ) - { - delete (XmlNode *)lChildren[j]; - } - for( int j = 0; j < lPropNames.getSize(); j++ ) - { - delete (std::string *)lPropNames[j]; - } - for( int j = 0; j < lPropValues.getSize(); j++ ) - { - delete (std::string *)lPropValues[j]; - } - for( int j = 0; j < lPostContent.getSize(); j++ ) - { - if( lPostContent[j] != NULL ) - { - delete (std::string *)lPostContent[j]; - } - } - if( sPreContent ) - { - delete sPreContent; - } -} - -void XmlNode::setName( const char *sName ) -{ - if( pParent ) - { - if( this->sName.size() == 0 ) - { - // We're not in the hash yet, so add us - this->sName = sName; - pParent->hChildren.insert( this->sName.c_str(), this ); - } - else - { - // Slightly more tricky, delete us, then add us... - pParent->hChildren.del( this->sName.c_str() ); - this->sName = sName; - pParent->hChildren.insert( this->sName.c_str(), this ); - } - } - else - { - // If we have no parent, then just set the name string, we don't need - // to worry about hashing. - this->sName = sName; - } -} - -void XmlNode::setContent( const char *sContent, int nIndex ) -{ - if( nIndex == -1 ) - { - nIndex = nCurContent; - } - if( nIndex == 0 ) - { - if( this->sPreContent ) - { - delete this->sPreContent; - } - - this->sPreContent = new std::string( sContent ); - } - else - { - nIndex--; - if( lPostContent[nIndex] ) - { - delete (std::string *)lPostContent[nIndex]; - } - - lPostContent.setAt( nIndex, new std::string( sContent ) ); - } -} - -const char *XmlNode::getContent( int nIndex ) -{ - if( nIndex == 0 ) - { - if( sPreContent ) - { - return sPreContent->c_str(); - } - } - else - { - nIndex--; - if( lPostContent[nIndex] ) - { - return ((std::string *)lPostContent[nIndex])->c_str(); - } - } - - return NULL; -} - -XmlNode *XmlNode::addChild( const char *sName, const char *sContent ) -{ - return addChild( new XmlNode( sName, this, sContent ) ); -} - -XmlNode *XmlNode::addChild( XmlNode *pNode ) -{ - lChildren.append( pNode ); - lPostContent.append( NULL ); - nCurContent++; - pNode->pParent = this; - - return pNode; -} - -XmlNode *XmlNode::getParent() -{ - return pParent; -} - -void XmlNode::addProperty( const char *sName, const char *sValue ) -{ - std::string *pName = new std::string( sName ); - std::string *pValue = new std::string( sValue ); - - hProperties.insert( pName->c_str(), pValue->c_str() ); - lPropNames.append( pName ); - lPropValues.append( pValue ); -} - -int XmlNode::getNumProperties() -{ - return lPropNames.getSize(); -} - -const char *XmlNode::getPropertyName( int nIndex ) -{ - std::string *tmp = ((std::string *)lPropNames[nIndex]); - if( tmp == NULL ) - return NULL; - return tmp->c_str(); -} - -const char *XmlNode::getProperty( int nIndex ) -{ - std::string *tmp = ((std::string *)lPropValues[nIndex]); - if( tmp == NULL ) - return NULL; - return tmp->c_str(); -} - -const char *XmlNode::getProperty( const char *sName ) -{ - const char *tmp = (const char *)hProperties[sName]; - if( tmp == NULL ) - return NULL; - return tmp; -} - -void XmlNode::deleteProperty( int nIndex ) -{ - hProperties.del( ((std::string *)lPropNames[nIndex])->c_str() ); - - delete (std::string *)lPropNames[nIndex]; - delete (std::string *)lPropValues[nIndex]; - - lPropNames.deleteAt( nIndex ); - lPropValues.deleteAt( nIndex ); -} - -bool XmlNode::hasChildren() -{ - return lChildren.getSize()>0; -} - -int XmlNode::getNumChildren() -{ - return lChildren.getSize(); -} - -XmlNode *XmlNode::getChild( int nIndex ) -{ - return (XmlNode *)lChildren[nIndex]; -} - -XmlNode *XmlNode::getChild( const char *sName, int nSkip ) -{ - return (XmlNode *)hChildren.get( sName, nSkip ); -} - -const char *XmlNode::getName() -{ - return sName.c_str(); -} - -void XmlNode::deleteNode( int nIndex, const char *sReplacementText ) -{ - XmlNode *xRet = detatchNode( nIndex, sReplacementText ); - - if( xRet != NULL ) - { - delete xRet; - } -} - -XmlNode *XmlNode::detatchNode( int nIndex, const char *sReplacementText ) -{ - if( nIndex < 0 || nIndex >= lChildren.getSize() ) - return NULL; - - // The real trick when deleteing a node isn't actually deleting it, it's - // reforming the content around the node that's now missing...hmmm... - - if( nIndex == 0 ) - { - // If the index is zero we have to deal with the pre-content - if( sReplacementText ) - { - if( sPreContent == NULL ) - { - sPreContent = new std::string( sReplacementText ); - } - else - { - *sPreContent += sReplacementText; - } - } - if( lPostContent.getSize() > 0 ) - { - if( lPostContent[0] != NULL ) - { - if( sPreContent == NULL ) - { - sPreContent = new std::string( - ((std::string *)lPostContent[0])->c_str() - ); - } - else - { - *sPreContent += - ((std::string *)lPostContent[0])->c_str(); - } - } - delete (std::string *)lPostContent[0]; - lPostContent.deleteAt( 0 ); - } - } - else - { - int nCont = nIndex-1; - // If it's above zero we deal with the post-content only - if( sReplacementText ) - { - if( lPostContent[nCont] == NULL ) - { - lPostContent.setAt( nCont, new std::string( sReplacementText ) ); - } - else - { - *((std::string *)lPostContent[nCont]) += sReplacementText; - } - } - if( lPostContent.getSize() > nIndex ) - { - if( lPostContent[nIndex] != NULL ) - { - if( lPostContent[nCont] == NULL ) - { - lPostContent.setAt( nCont, new std::string( - ((std::string *)lPostContent[nIndex])->c_str() - ) ); - } - else - { - *((std::string *)lPostContent[nCont]) += - ((std::string *)lPostContent[nIndex])->c_str(); - } - } - delete (std::string *)lPostContent[nIndex]; - lPostContent.deleteAt( nIndex ); - } - } - - XmlNode *xRet = (XmlNode *)lChildren[nIndex]; - hChildren.del( ((XmlNode *)lChildren[nIndex])->getName() ); - lChildren.deleteAt( nIndex ); - - return xRet; -} - -void XmlNode::replaceNode( int nIndex, XmlNode *pNewNode ) -{ - if( nIndex < 0 || nIndex >= lChildren.getSize() ) - return; //TODO: throw an exception - - delete (XmlNode *)lChildren[nIndex]; - lChildren.setAt( nIndex, pNewNode ); - pNewNode->pParent = this; -} - -XmlNode *XmlNode::getCopy() -{ - XmlNode *pNew = new XmlNode(); - - pNew->sName = sName; - if( sPreContent ) - { - pNew->sPreContent = new std::string( sPreContent->c_str() ); - } - else - { - pNew->sPreContent = NULL; - } - pNew->nCurContent = 0; - - int nSize = lPostContent.getSize(); - pNew->lPostContent.setSize( nSize ); - for( int j = 0; j < nSize; j++ ) - { - if( lPostContent[j] ) - { - pNew->lPostContent.setAt( - j, new std::string( - ((std::string *)lPostContent[j])->c_str() - ) - ); - } - else - { - pNew->lPostContent.setAt( j, NULL ); - } - } - - nSize = lChildren.getSize(); - pNew->lChildren.setSize( nSize ); - for( int j = 0; j < nSize; j++ ) - { - XmlNode *pChild = ((XmlNode *)lChildren[j])->getCopy(); - pNew->lChildren.setAt( j, pChild ); - pChild->pParent = pNew; - pNew->hChildren.insert( pChild->getName(), pChild ); - } - - nSize = lPropNames.getSize(); - pNew->lPropNames.setSize( nSize ); - pNew->lPropValues.setSize( nSize ); - for( int j = 0; j < nSize; j++ ) - { - std::string *pProp = new std::string( ((std::string *)lPropNames[j])->c_str() ); - std::string *pVal = new std::string( ((std::string *)lPropValues[j])->c_str() ); - pNew->lPropNames.setAt( j, pProp ); - pNew->lPropValues.setAt( j, pVal ); - pNew->hProperties.insert( pProp->c_str(), pVal->c_str() ); - pNew->nCurContent++; - } - - return pNew; -} - -void XmlNode::deleteNodeKeepChildren( int nIndex ) -{ - // This is a tricky one...we need to do some patching to keep things all - // even... - XmlNode *xRet = (XmlNode *)lChildren[nIndex]; - - if( xRet == NULL ) - { - return; - } - else - { - if( getContent( nIndex ) ) - { - std::string sBuf( getContent( nIndex ) ); - sBuf += xRet->getContent( 0 ); - setContent( sBuf.c_str(), nIndex ); - } - else - { - setContent( xRet->getContent( 0 ), nIndex ); - } - - int nSize = xRet->lChildren.getSize(); - for( int j = 0; j < nSize; j++ ) - { - XmlNode *pCopy = ((XmlNode *)xRet->lChildren[j])->getCopy(); - pCopy->pParent = this; - lChildren.insertBefore( pCopy, nIndex+j ); - - if( xRet->lPostContent[j] ) - { - lPostContent.insertBefore( - new std::string( ((std::string *)xRet->lPostContent[j])->c_str() ), - nIndex+j - ); - } - else - { - lPostContent.insertBefore( NULL, nIndex+j ); - } - } - - if( getContent( nIndex+nSize ) ) - { - //SString sBuf( getContent( nIndex+nSize ) ); - //sBuf.catfrom( xRet->getContent( nSize ) ); - //setContent( sBuf, nIndex+nSize ); - } - else - { - setContent( xRet->getContent( nSize ), nIndex+nSize ); - } - - deleteNode( nIndex+nSize ); - } -} - -void XmlNode::replaceNodeWithChildren( int nIndex, XmlNode *pNewNode ) -{ -} - diff --git a/src/xmlnode.h b/src/xmlnode.h deleted file mode 100644 index 7525306..0000000 --- a/src/xmlnode.h +++ /dev/null @@ -1,236 +0,0 @@ -#ifndef XMLNODE -#define XMLNODE - -#include <iostream> -#include "linkedlist.h" -#include "hashtable.h" - -/** - * Maintains all data pertient to an XML node, including sub-nodes and content. - * All child nodes can be accessed through index and through name via a hash - * table. This makes it very easy to gain simple and fast access to all of - * your data. For most applications, the memory footprint is also rather - * small. While XmlNode objects can be used directly to create XML structures - * it is highly reccomended that all operations be performed through the - * XmlDocument class. - *@author Mike Buland - */ -class XmlNode -{ -public: - /** - * Construct a new XmlNode. - *@param sName The name of the node. - *@param pParent The parent node. - *@param sContent The initial content string. - */ - XmlNode( - const char *sName=NULL, - XmlNode *pParent = NULL, - const char *sContent=NULL - ); - - /** - * Delete the node and cleanup all memory. - */ - virtual ~XmlNode(); - - /** - * Change the name of the node. - *@param sName The new name of the node. - */ - void setName( const char *sName ); - - /** - * Construct a new node and add it as a child to this node, also return a - * pointer to the newly constructed node. - *@param sName The name of the new node. - *@param sContent The initial content of the new node. - *@returns A pointer to the newly created child node. - */ - XmlNode *addChild( const char *sName, const char *sContent=NULL ); - - /** - * Add an already created XmlNode as a child to this node. The new child - * XmlNode's parent will be changed appropriately and the parent XmlNode - * will take ownership of the child. - *@param pChild The child XmlNode to add to this XmlNode. - *@returns A pointer to the child node that was just added. - */ - XmlNode *addChild( XmlNode *pChild ); - - /** - * Add a new property to the XmlNode. Properties are name/value pairs. - *@param sName The name of the property. Specifying a name that's already - * in use will overwrite that property. - *@param sValue The textual value of the property. - */ - void addProperty( const char *sName, const char *sValue ); - - /** - * Get a pointer to the parent node, if any. - *@returns A pointer to the node's parent, or NULL if there isn't one. - */ - XmlNode *getParent(); - - /** - * Tells you if this node has children. - *@returns True if this node has at least one child, false otherwise. - */ - bool hasChildren(); - - /** - * Tells you how many children this node has. - *@returns The number of children this node has. - */ - int getNumChildren(); - - /** - * Get a child node at a specific index. - *@param nIndex The zero-based index of the child to retreive. - *@returns A pointer to the child, or NULL if you requested an invalid - * index. - */ - XmlNode *getChild( int nIndex ); - - /** - * Get a child with the specified name, and possibly skip value. For an - * explination of skip values see the HashTable. - *@param sName The name of the child to find. - *@param nSkip The number of nodes with that name to skip. - *@returns A pointer to the child, or NULL if no child with that name was - * found. - */ - XmlNode *getChild( const char *sName, int nSkip=0 ); - - /** - * Get a pointer to the name of this node. Do not change this, use setName - * instead. - *@returns A pointer to the name of this node. - */ - const char *getName(); - - /** - * Set the content of this node, optionally at a specific index. Using the - * default of -1 will set the content after the last added node. - *@param sContent The content string to use. - *@param nIndex The index of the content. - */ - void setContent( const char *sContent, int nIndex=-1 ); - - /** - * Get the content string at a given index, or zero for initial content. - *@param nIndex The index of the content. - *@returns A pointer to the content at that location. - */ - const char *getContent( int nIndex = 0 ); - - /** - * Get the number of properties in this node. - *@returns The number of properties in this node. - */ - int getNumProperties(); - - /** - * Get a property's name by index. - *@param nIndex The index of the property to examine. - *@returns A pointer to the name of the property specified, or NULL if none - * found. - */ - const char *getPropertyName( int nIndex ); - - /** - * Get a proprty's value by index. - *@param nIndex The index of the property to examine. - *@returns A pointer to the value of the property specified, or NULL if none - * found. - */ - const char *getProperty( int nIndex ); - - /** - * Get a propery's value by name. - *@param sName The name of the property to examine. - *@returns A pointer to the value of the property specified, or NULL if none - * found. - */ - const char *getProperty( const char *sName ); - - /** - * Delete a property by index. - *@param nIndex The index of the property to delete. - *@returns True if the property was found and deleted, false if it wasn't - * found. - */ - void deleteProperty( int nIndex ); - - /** - * Delete a child node, possibly replacing it with some text. This actually - * fixes all content strings around the newly deleted child node. - *@param nIndex The index of the node to delete. - *@param sReplacementText The optional text to replace the node with. - *@returns True of the node was found, and deleted, false if it wasn't - * found. - */ - void deleteNode( int nIndex, const char *sReplacementText = NULL ); - - /** - * Delete a given node, but move all of it's children and content up to - * replace the deleted node. All of the content of the child node is - * spliced seamlessly into place with the parent node's content. - *@param nIndex The node to delete. - *@returns True if the node was found and deleted, false if it wasn't. - */ - void deleteNodeKeepChildren( int nIndex ); - - /** - * Detatch a given child node from this node. This effectively works just - * like a deleteNode, except that instead of deleting the node it is removed - * and returned, and all ownership is given up. - *@param nIndex The index of the node to detatch. - *@param sReplacementText The optional text to replace the detatched node - * with. - *@returns A pointer to the newly detatched node, which then passes - * ownership to the caller. - */ - XmlNode *detatchNode( int nIndex, const char *sReplacementText = NULL ); - - /** - * Replace a given node with a different node that is not currently owned by - * this XmlNode or any ancestor. - *@param nIndex The index of the node to replace. - *@param pNewNode The new node to replace the old node with. - *@returns True if the node was found and replaced, false if it wasn't. - */ - void replaceNode( int nIndex, XmlNode *pNewNode ); - - /** - * Replace a given node with the children and content of a given node. - *@param nIndex The index of the node to replace. - *@param pNewNode The node that contains the children and content that will - * replace the node specified by nIndex. - *@returns True if the node was found and replaced, false if it wasn't. - */ - void replaceNodeWithChildren( int nIndex, XmlNode *pNewNode ); - - /** - * Get a copy of this node and all children. getCopy is recursive, so - * beware copying large trees of xml. - *@returns A newly created copy of this node and all of it's children. - */ - XmlNode *getCopy(); - -private: - std::string sName; /**< The name of the node. */ - std::string *sPreContent; /**< The content that goes before any node. */ - LinkedList lChildren; /**< The children. */ - LinkedList lPostContent; /**< The content that comes after children. */ - HashTable hProperties; /**< Property hashtable. */ - HashTable hChildren; /**< Children hashtable. */ - LinkedList lPropNames; /**< List of property names. */ - LinkedList lPropValues; /**< List of property values. */ - XmlNode *pParent; /**< A pointer to the parent of this node. */ - int nCurContent; /**< The current content we're on, for using the -1 on - setContent. */ -}; - -#endif diff --git a/src/xmlreader.cpp b/src/xmlreader.cpp deleted file mode 100644 index 18df69c..0000000 --- a/src/xmlreader.cpp +++ /dev/null @@ -1,602 +0,0 @@ -#include "xmlreader.h" -#include "exceptions.h" -#include <string.h> -#include "hashfunctionstring.h" - -XmlReader::XmlReader( bool bStrip ) : - bStrip( bStrip ), - htEntity( new HashFunctionString(), 11 ) -{ -} - -XmlReader::~XmlReader() -{ - void *i = htEntity.getFirstItemPos(); - while( (i = htEntity.getNextItemPos( i ) ) ) - { - free( (char *)(htEntity.getItemID( i )) ); - delete (StaticString *)htEntity.getItemData( i ); - } -} - -void XmlReader::addEntity( const char *name, const char *value ) -{ - if( htEntity[name] ) return; - - char *sName = strdup( name ); - StaticString *sValue = new StaticString( value ); - - htEntity.insert( sName, sValue ); -} - -#define gcall( x ) if( x == false ) return false; - -bool XmlReader::isws( char chr ) -{ - return ( chr == ' ' || chr == '\t' || chr == '\n' || chr == '\r' ); -} - -bool XmlReader::ws() -{ - while( true ) - { - char chr = getChar(); - if( isws( chr ) ) - { - usedChar(); - } - else - { - return true; - } - } - return true; -} - -bool XmlReader::buildDoc() -{ - // take care of initial whitespace - gcall( ws() ); - textDecl(); - entity(); - addEntity("gt", ">"); - addEntity("lt", "<"); - addEntity("amp", "&"); - addEntity("apos", "\'"); - addEntity("quot", "\""); - gcall( node() ); - - return true; -} - -void XmlReader::textDecl() -{ - if( getChar() == '<' && getChar( 1 ) == '?' ) - { - usedChar( 2 ); - for(;;) - { - if( getChar() == '?' ) - { - if( getChar( 1 ) == '>' ) - { - usedChar( 2 ); - return; - } - } - usedChar(); - } - } -} - -void XmlReader::entity() -{ - for(;;) - { - ws(); - - if( getChar() == '<' && getChar( 1 ) == '!' ) - { - usedChar( 2 ); - ws(); - std::string buf; - for(;;) - { - char chr = getChar(); - usedChar(); - if( isws( chr ) ) break; - buf += chr; - } - - if( strcmp( buf.c_str(), "ENTITY") == 0 ) - { - ws(); - std::string name; - for(;;) - { - char chr = getChar(); - usedChar(); - if( isws( chr ) ) break; - name += chr; - } - ws(); - char quot = getChar(); - usedChar(); - if( quot != '\'' && quot != '\"' ) - { - throw XmlException( - "Only quoted entity values are supported." - ); - } - std::string value; - for(;;) - { - char chr = getChar(); - usedChar(); - if( chr == '&' ) - { - StaticString *tmp = getEscape(); - if( tmp == NULL ) throw XmlException("Entity thing"); - value += tmp->getString(); - delete tmp; - } - else if( chr == quot ) - { - break; - } - else - { - value += chr; - } - } - ws(); - if( getChar() == '>' ) - { - usedChar(); - - addEntity( name.c_str(), value.c_str() ); - } - else - { - throw XmlException( - "Malformed ENTITY: unexpected '%c' found.", - getChar() - ); - } - } - else - { - throw XmlException( - "Unsupported header symbol: %s", - buf.c_str() - ); - } - } - else - { - return; - } - } -} - -bool XmlReader::node() -{ - gcall( startNode() ) - - // At this point, we are closing the startNode - char chr = getChar(); - if( chr == '>' ) - { - usedChar(); - - // Now we process the guts of the node. - gcall( content() ); - } - else if( chr == '/' ) - { - // This is the tricky one, one more validation, then we close the node. - usedChar(); - if( getChar() == '>' ) - { - closeNode(); - usedChar(); - } - else - { - throw XmlException("Close node in singleNode malformed!"); - } - } - else - { - throw XmlException("Close node expected, but not found."); - return false; - } - - return true; -} - -bool XmlReader::startNode() -{ - if( getChar() == '<' ) - { - usedChar(); - - if( getChar() == '/' ) - { - // Heh, it's actually a close node, go figure - FlexBuf fbName; - usedChar(); - gcall( ws() ); - - while( true ) - { - char chr = getChar(); - if( isws( chr ) || chr == '>' ) - { - // Here we actually compare the name we got to the name - // we already set, they have to match exactly. - if( !strcasecmp( getCurrent()->getName(), fbName.getData() ) ) - { - closeNode(); - break; - } - else - { - throw XmlException("Got a mismatched node close tag."); - } - } - else - { - fbName.appendData( chr ); - usedChar(); - } - } - - gcall( ws() ); - if( getChar() == '>' ) - { - // Everything is cool. - usedChar(); - } - else - { - throw XmlException("Got extra junk data instead of node close tag."); - } - } - else - { - // We're good, format is consistant - addNode(); - - // Skip extra whitespace - gcall( ws() ); - gcall( name() ); - gcall( ws() ); - gcall( paramlist() ); - gcall( ws() ); - } - } - else - { - throw XmlException("Expected to find node opening char, '<'."); - } - - return true; -} - -bool XmlReader::name() -{ - FlexBuf fbName; - - while( true ) - { - char chr = getChar(); - if( isws( chr ) || chr == '>' || chr == '/' ) - { - setName( fbName.getData() ); - return true; - } - else - { - fbName.appendData( chr ); - usedChar(); - } - } - - return true; -} - -bool XmlReader::paramlist() -{ - while( true ) - { - char chr = getChar(); - if( chr == '/' || chr == '>' ) - { - return true; - } - else - { - gcall( param() ); - gcall( ws() ); - } - } - - return true; -} - -StaticString *XmlReader::getEscape() -{ - if( getChar( 1 ) == '#' ) - { - // If the entity starts with a # it's a character escape code - int base = 10; - usedChar( 2 ); - if( getChar() == 'x' ) - { - base = 16; - usedChar(); - } - char buf[4]; - int j = 0; - for( j = 0; getChar() != ';'; j++ ) - { - buf[j] = getChar(); - usedChar(); - } - usedChar(); - buf[j] = '\0'; - buf[0] = (char)strtol( buf, (char **)NULL, base ); - buf[1] = '\0'; - - return new StaticString( buf ); - } - else - { - // ...otherwise replace with the appropriate string... - std::string buf; - usedChar(); - for(;;) - { - char cbuf = getChar(); - usedChar(); - if( cbuf == ';' ) break; - buf += cbuf; - } - - StaticString *tmp = (StaticString *)htEntity[buf.c_str()]; - if( tmp == NULL ) return NULL; - - StaticString *ret = new StaticString( *tmp ); - return ret; - } -} - -bool XmlReader::param() -{ - FlexBuf fbName; - FlexBuf fbValue; - - while( true ) - { - char chr = getChar(); - if( isws( chr ) || chr == '=' ) - { - break; - } - else - { - fbName.appendData( chr ); - usedChar(); - } - } - - gcall( ws() ); - - if( getChar() == '=' ) - { - usedChar(); - - gcall( ws() ); - - char chr = getChar(); - if( chr == '"' ) - { - // Better quoted rhs - usedChar(); - - while( true ) - { - chr = getChar(); - if( chr == '"' ) - { - usedChar(); - addProperty( fbName.getData(), fbValue.getData() ); - return true; - } - else - { - if( chr == '&' ) - { - StaticString *tmp = getEscape(); - if( tmp == NULL ) return false; - fbValue.appendData( tmp->getString() ); - delete tmp; - } - else - { - fbValue.appendData( chr ); - usedChar(); - } - } - } - } - else - { - // Simple one-word rhs - while( true ) - { - chr = getChar(); - if( isws( chr ) || chr == '/' || chr == '>' ) - { - addProperty( fbName.getData(), fbValue.getData() ); - return true; - } - else - { - if( chr == '&' ) - { - StaticString *tmp = getEscape(); - if( tmp == NULL ) return false; - fbValue.appendData( tmp->getString() ); - delete tmp; - } - else - { - fbValue.appendData( chr ); - usedChar(); - } - } - } - } - } - else - { - throw XmlException("Expected an equals to seperate the params."); - return false; - } - - return true; -} - -bool XmlReader::content() -{ - FlexBuf fbContent; - - if( bStrip ) gcall( ws() ); - - while( true ) - { - char chr = getChar(); - if( chr == '<' ) - { - if( getChar(1) == '/' ) - { - if( fbContent.getLength() > 0 ) - { - if( bStrip ) - { - int j; - for( j = fbContent.getLength()-1; isws(fbContent.getData()[j]); j-- ); - ((char *)fbContent.getData())[j+1] = '\0'; - } - setContent( fbContent.getData() ); - } - usedChar( 2 ); - gcall( ws() ); - FlexBuf fbName; - while( true ) - { - chr = getChar(); - if( isws( chr ) || chr == '>' ) - { - if( !strcasecmp( getCurrent()->getName(), fbName.getData() ) ) - { - closeNode(); - break; - } - else - { - throw XmlException("Mismatched close tag found: <%s> to <%s>.", getCurrent()->getName(), fbName.getData() ); - } - } - else - { - fbName.appendData( chr ); - usedChar(); - } - } - gcall( ws() ); - if( getChar() == '>' ) - { - usedChar(); - return true; - } - else - { - throw XmlException("Malformed close tag."); - } - } - else if( getChar(1) == '!' ) - { - // We know it's a comment, let's see if it's proper - if( getChar(2) != '-' || - getChar(3) != '-' ) - { - // Not a valid XML comment - throw XmlException("Malformed comment start tag found."); - } - - usedChar( 4 ); - - // Now burn text until we find the close tag - for(;;) - { - if( getChar() == '-' ) - { - if( getChar( 1 ) == '-' ) - { - // The next one has to be a '>' now - if( getChar( 2 ) != '>' ) - { - throw XmlException("Malformed comment close tag found. You cannot have a '--' that isn't followed by a '>' in a comment."); - } - usedChar( 3 ); - break; - } - else - { - // Found a dash followed by a non dash, that's ok... - usedChar( 2 ); - } - } - else - { - // Burn comment chars - usedChar(); - } - } - } - else - { - if( fbContent.getLength() > 0 ) - { - if( bStrip ) - { - int j; - for( j = fbContent.getLength()-1; isws(fbContent.getData()[j]); j-- ); - ((char *)fbContent.getData())[j+1] = '\0'; - } - setContent( fbContent.getData() ); - fbContent.clearData(); - } - gcall( node() ); - } - - if( bStrip ) gcall( ws() ); - } - else if( chr == '&' ) - { - StaticString *tmp = getEscape(); - if( tmp == NULL ) return false; - fbContent.appendData( tmp->getString() ); - delete tmp; - } - else - { - fbContent.appendData( chr ); - usedChar(); - } - } -} - diff --git a/src/xmlreader.h b/src/xmlreader.h deleted file mode 100644 index c8f7202..0000000 --- a/src/xmlreader.h +++ /dev/null @@ -1,141 +0,0 @@ -#ifndef XMLREADER -#define XMLREADER - -#include <stdio.h> -#include "xmldocument.h" -#include "flexbuf.h" -#include "hashtable.h" -#include "staticstring.h" - -/** - * Takes care of reading in xml formatted data from a file. This could/should - * be made more arbitrary in the future so that we can read the data from any - * source. This is actually made quite simple already since all data read in - * is handled by one single helper function and then palced into a FlexBuf for - * easy access by the other functions. The FlexBuf also allows for block - * reading from disk, which improves speed by a noticable amount. - * <br> - * There are also some extra features implemented that allow you to break the - * standard XML reader specs and eliminate leading and trailing whitespace in - * all read content. This is useful in situations where you allow additional - * whitespace in the files to make them easily human readable. The resturned - * content will be NULL in sitautions where all content between nodes was - * stripped. - *@author Mike Buland - */ -class XmlReader : public XmlDocument -{ -public: - /** - * Create a standard XmlReader. The optional parameter bStrip allows you to - * create a reader that will strip out all leading and trailing whitespace - * in content, a-la html. - *@param bStrip Strip out leading and trailing whitespace? - */ - XmlReader( bool bStrip=false ); - - /** - * Destroy this XmlReader. - */ - virtual ~XmlReader(); - - /** - * Build a document based on some kind of input. This is called - * automatically by the constructor. - */ - bool buildDoc(); - -private: - /** - * This is called by the low level automoton in order to get the next - * character. This function should return a character at the current - * position plus nIndex, but does not increment the current character. - *@param nIndex The index of the character from the current stream position. - *@returns A single character at the requested position, or 0 for end of - * stream. - */ - virtual char getChar( int nIndex = 0 ) = 0; - - /** - * Called to increment the current stream position by a single character. - */ - virtual void usedChar( int nAmnt = 1) = 0; - - /** - * Automoton function: is whitespace. - *@param chr A character - *@returns True if chr is whitespace, false otherwise. - */ - bool isws( char chr ); - - /** - * Automoton function: ws. Skips sections of whitespace. - *@returns True if everything was ok, False for end of stream. - */ - bool ws(); - - /** - * Automoton function: node. Processes an XmlNode - *@returns True if everything was ok, False for end of stream. - */ - bool node(); - - /** - * Automoton function: startNode. Processes the begining of a node. - *@returns True if everything was ok, False for end of stream. - */ - bool startNode(); - - /** - * Automoton function: name. Processes the name of a node. - *@returns True if everything was ok, False for end of stream. - */ - bool name(); - - /** - * Automoton function: textDecl. Processes the xml text decleration, if - * there is one. - */ - void textDecl(); - - /** - * Automoton function: entity. Processes an entity from the header. - */ - void entity(); - - /** - * Adds an entity to the list, if it doesn't already exist. - *@param name The name of the entity - *@param value The value of the entity - */ - void addEntity( const char *name, const char *value ); - - StaticString *getEscape(); - - /** - * Automoton function: paramlist. Processes a list of node params. - *@returns True if everything was ok, False for end of stream. - */ - bool paramlist(); - - /** - * Automoton function: param. Processes a single parameter. - *@returns True if everything was ok, False for end of stream. - */ - bool param(); - - /** - * Automoton function: content. Processes node content. - *@returns True if everything was ok, False for end of stream. - */ - bool content(); - - FlexBuf fbContent; /**< buffer for the current node's content. */ - FlexBuf fbParamName; /**< buffer for the current param's name. */ - FlexBuf fbParamValue; /**< buffer for the current param's value. */ - bool bStrip; /**< Are we stripping whitespace? */ - - HashTable htEntity; /**< Entity type definitions. */ -}; - -#endif diff --git a/src/xmlstringreader.cpp b/src/xmlstringreader.cpp deleted file mode 100644 index 3956ff3..0000000 --- a/src/xmlstringreader.cpp +++ /dev/null @@ -1,38 +0,0 @@ -#include "xmlstringreader.h" -#include "exceptions.h" -#include <string.h> - -XmlStringReader::XmlStringReader( const char *sString, bool bStrip ) - : XmlReader( bStrip ) -{ - this->sString = sString; - - nIndex = 0; - nLength = strlen( sString ); - - buildDoc(); -} - -XmlStringReader::~XmlStringReader() -{ -} - -char XmlStringReader::getChar( int nAdd ) -{ - if( nLength >= nIndex+nAdd+1 ) - { - return sString[nIndex+nAdd]; - } - else - { - throw XmlException("End of XML stream read."); - } -} - -void XmlStringReader::usedChar( int nAmnt ) -{ - if( nLength >= nIndex+nAmnt ) - { - nIndex += nAmnt; - } -} diff --git a/src/xmlstringreader.h b/src/xmlstringreader.h deleted file mode 100644 index 1239ef4..0000000 --- a/src/xmlstringreader.h +++ /dev/null @@ -1,49 +0,0 @@ -#ifndef XMLSTRINGREADER -#define XMLSTRINGREADER - -#include <stdio.h> -#include "xmlreader.h" -#include "flexbuf.h" - -/** - * Takes care of reading in xml formatted data from a file. This could/should - * be made more arbitrary in the future so that we can read the data from any - * source. This is actually made quite simple already since all data read in - * is handled by one single helper function and then palced into a FlexBuf for - * easy access by the other functions. The FlexBuf also allows for block - * reading from disk, which improves speed by a noticable amount. - * <br> - * There are also some extra features implemented that allow you to break the - * standard XML reader specs and eliminate leading and trailing whitespace in - * all read content. This is useful in situations where you allow additional - * whitespace in the files to make them easily human readable. The resturned - * content will be NULL in sitautions where all content between nodes was - * stripped. - *@author Mike Buland - */ -class XmlStringReader : public XmlReader -{ -public: - /** - * Create a new string reader around an already created and formatted - * null-terminated string. - *@param sString A pointer to the string data that will be used. This data - * is not changed during processing. - *@param bStrip Strip out leading and trailing whitespace. - */ - XmlStringReader( const char *sString, bool bStrip=false ); - - /** - * Destroy this string reader. - */ - virtual ~XmlStringReader(); - -private: - char getChar( int nIndex = 0 ); - void usedChar( int nAmnt = 1 ); - const char *sString; /**< Internal pointer to the input string. */ - int nIndex; /**< Our index into the string */ - int nLength; /**< The computed length of the string */ -}; - -#endif diff --git a/src/xmlstringwriter.cpp b/src/xmlstringwriter.cpp deleted file mode 100644 index adeed6a..0000000 --- a/src/xmlstringwriter.cpp +++ /dev/null @@ -1,23 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> -#include "xmlstringwriter.h" - -XmlStringWriter::XmlStringWriter( const char *sIndent ) : - XmlWriter( sIndent ) -{ -} - -XmlStringWriter::~XmlStringWriter() -{ -} - -void XmlStringWriter::writeString( const char *sString ) -{ - sXml += sString; -} - -std::string &XmlStringWriter::getString() -{ - return sXml; -} - diff --git a/src/xmlstringwriter.h b/src/xmlstringwriter.h deleted file mode 100644 index 0d567b9..0000000 --- a/src/xmlstringwriter.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef XML_STRING_WRITER -#define XML_STRING_WRITER - -#include "xmlnode.h" -#include "xmlwriter.h" - -/** - * Implements xml writing in the XML standard format. Also allows you to - * break that format and auto-indent your exported xml data for ease of - * reading. The auto-indenting will only be applied to sections that - * have no content of their own already. This means that except for - * whitespace all of your data will be preserved perfectly. - * You can create an XmlWriter object around a file, or access the static - * write function directly and just hand it a filename and a root XmlNode. - * When using an XmlWriter object the interface is identicle to that of - * the XmlDocument class, so reference that class for API info. However - * when the initial (or root) node is closed, and the document is finished - * the file will be created and written to automatically. The user can - * check to see if this is actually true by calling the isFinished - * function in the XmlDocument class. - *@author Mike Buland - */ -class XmlStringWriter : public XmlWriter -{ -public: - /** - * Construct a string writer using an internal string buffer. - *@param sIndent Optional indent to add to each line. - */ - XmlStringWriter( const char *sIndent=NULL ); - - /** - * Destroy the string writer and the internal string. - */ - virtual ~XmlStringWriter(); - - /** - * Get the string that was built. This is only valid after the document has - * been completed, so check isCompleted or be sure your addNode and - * closeNode calls match up. - *@returns A reference to the internal string object. - */ - std::string &getString(); - -private: - void writeString( const char *sString ); - std::string sXml; /**< The string object we "write" to. */ -}; - -#endif diff --git a/src/xmlwriter.cpp b/src/xmlwriter.cpp deleted file mode 100644 index 56880b6..0000000 --- a/src/xmlwriter.cpp +++ /dev/null @@ -1,173 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> -#include "xmlwriter.h" - -XmlWriter::XmlWriter( const char *sIndent, XmlNode *pRoot ) : - XmlDocument( pRoot ) -{ - if( sIndent == NULL ) - { - this->sIndent = ""; - } - else - { - this->sIndent = sIndent; - } -} - -XmlWriter::~XmlWriter() -{ -} - -void XmlWriter::write() -{ - write( getRoot(), sIndent.c_str() ); -} - -void XmlWriter::write( XmlNode *pRoot, const char *sIndent ) -{ - writeNode( pRoot, 0, sIndent ); -} - -void XmlWriter::closeNode() -{ - XmlDocument::closeNode(); - - if( isCompleted() ) - { - write( getRoot(), sIndent.c_str() ); - } -} - -void XmlWriter::writeIndent( int nIndent, const char *sIndent ) -{ - if( sIndent == NULL ) return; - for( int j = 0; j < nIndent; j++ ) - { - writeString( sIndent ); - } -} - -std::string XmlWriter::escape( std::string sIn ) -{ - std::string sOut; - - std::string::const_iterator i; - for( i = sIn.begin(); i != sIn.end(); i++ ) - { - if( ((*i >= ' ' && *i <= '9') || - (*i >= 'a' && *i <= 'z') || - (*i >= 'A' && *i <= 'Z') ) && - (*i != '\"' && *i != '\'' && *i != '&') - ) - { - sOut += *i; - } - else - { - sOut += "&#"; - char buf[4]; - sprintf( buf, "%u", (unsigned char)*i ); - sOut += buf; - sOut += ';'; - } - } - - return sOut; -} - -void XmlWriter::writeNodeProps( XmlNode *pNode, int nIndent, const char *sIndent ) -{ - for( int j = 0; j < pNode->getNumProperties(); j++ ) - { - writeString(" "); - writeString( pNode->getPropertyName( j ) ); - writeString("=\""); - writeString( escape( pNode->getProperty( j ) ).c_str() ); - writeString("\""); - } -} - -void XmlWriter::writeNode( XmlNode *pNode, int nIndent, const char *sIndent ) -{ - if( pNode->hasChildren() ) - { - writeIndent( nIndent, sIndent ); - writeString("<"); - writeString( pNode->getName() ); - writeNodeProps( pNode, nIndent, sIndent ); - if( sIndent ) - writeString(">\n"); - else - writeString(">"); - - if( pNode->getContent( 0 ) ) - { - writeIndent( nIndent+1, sIndent ); - if( sIndent ) - { - writeString( pNode->getContent( 0 ) ); - writeString("\n"); - } - else - writeString( pNode->getContent( 0 ) ); - } - - int nNumChildren = pNode->getNumChildren(); - for( int j = 0; j < nNumChildren; j++ ) - { - writeNode( pNode->getChild( j ), nIndent+1, sIndent ); - if( pNode->getContent( j+1 ) ) - { - writeIndent( nIndent+1, sIndent ); - if( sIndent ) - { - writeString( pNode->getContent( j+1 ) ); - writeString("\n"); - } - else - writeString( pNode->getContent( j+1 ) ); - } - } - - writeIndent( nIndent, sIndent ); - if( sIndent ) - { - writeString("</"); - writeString( pNode->getName() ); - writeString(">\n"); - } - else - { - writeString("</"); - writeString( pNode->getName() ); - writeString(">"); - } - } - else if( pNode->getContent() ) - { - writeIndent( nIndent, sIndent ); - writeString("<"); - writeString( pNode->getName() ); - writeNodeProps( pNode, nIndent, sIndent ); - writeString(">"); - writeString( pNode->getContent() ); - writeString("</"); - writeString( pNode->getName() ); - writeString(">"); - if( sIndent ) - writeString("\n"); - } - else - { - writeIndent( nIndent, sIndent ); - writeString("<"); - writeString( pNode->getName() ); - writeNodeProps( pNode, nIndent, sIndent ); - if( sIndent ) - writeString("/>\n"); - else - writeString("/>"); - } -} - diff --git a/src/xmlwriter.h b/src/xmlwriter.h deleted file mode 100644 index c48e810..0000000 --- a/src/xmlwriter.h +++ /dev/null @@ -1,96 +0,0 @@ -#ifndef XMLWRITER -#define XMLWRITER - -#include "xmlnode.h" -#include "xmldocument.h" - -/** - * Implements xml writing in the XML standard format. Also allows you to - * break that format and auto-indent your exported xml data for ease of - * reading. The auto-indenting will only be applied to sections that - * have no content of their own already. This means that except for - * whitespace all of your data will be preserved perfectly. - * You can create an XmlWriter object around a file, or access the static - * write function directly and just hand it a filename and a root XmlNode. - * When using an XmlWriter object the interface is identicle to that of - * the XmlDocument class, so reference that class for API info. However - * when the initial (or root) node is closed, and the document is finished - * the file will be created and written to automatically. The user can - * check to see if this is actually true by calling the isFinished - * function in the XmlDocument class. - *@author Mike Buland - */ -class XmlWriter : public XmlDocument -{ -public: - /** - * Construct a standard XmlWriter. - *@param sIndent Set this to something other than NULL to include it as an - * indent before each node in the output that doesn't already have content. - * If you are using the whitespace stripping option in the XmlReader and set - * this to a tab or some spaces it will never effect the content of your - * file. - */ - XmlWriter( const char *sIndent=NULL, XmlNode *pRoot=NULL ); - - /** - * Destroy the writer. - */ - virtual ~XmlWriter(); - - /** - * This override of the parent class closeNode function calls the parent - * class, but also triggers a write operation when the final node is closed. - * This means that by checking the isCompleted() function the user may also - * check to see if their file has been written or not. - */ - void closeNode(); - - void write(); - -private: - std::string sIndent; /**< The indent string */ - - std::string escape( std::string sIn ); - - /** - * Write the file. - *@param pNode The root node - *@param sIndent The indent text. - */ - void write( XmlNode *pNode, const char *sIndent=NULL ); - - /** - * Write a node in the file, including children. - *@param pNode The node to write. - *@param nIndent The indent level (the number of times to include sIndent) - *@param sIndent The indent text. - */ - void writeNode( XmlNode *pNode, int nIndent, const char *sIndent ); - - /** - * Write the properties of a node. - *@param pNode The node who's properties to write. - *@param nIndent The indent level of the containing node - *@param sIndent The indent text. - */ - void writeNodeProps( XmlNode *pNode, int nIndent, const char *sIndent ); - - /** - * Called to write the actual indent. - *@param nIndent The indent level. - *@param sIndent The indent text. - */ - void writeIndent( int nIndent, const char *sIndent ); - - /** - * This is the function that must be overridden in order to use this class. - * It must write the null-terminated string sString, minus the mull, - * verbatum to it's output device. Adding extra characters for any reason - * will break the XML formatting. - *@param sString The string data to write to the output. - */ - virtual void writeString( const char *sString ) = 0; -}; - -#endif -- cgit v1.2.3