Merge lp:~fpstovall/nrtb/cpp_common into lp:nrtb

Proposed by Rick Stovall
Status: Merged
Approved by: Rick Stovall
Approved revision: 49
Merged at revision: 5
Proposed branch: lp:~fpstovall/nrtb/cpp_common
Merge into: lp:nrtb
Diff against target: 9400 lines (+6194/-2510)
62 files modified
GPB_proto/ack_nak.proto (+3/-0)
GPB_proto/physics_common.proto (+2/-0)
GPB_proto/sim_obj_tq_update.proto (+2/-0)
GPB_proto/sim_to_db_wrapper.proto (+2/-0)
common/GPB/Makefile (+34/-0)
common/Makefile (+31/-4)
common/common_rl/Makefile (+36/-0)
common/common_rl/common.cpp (+274/-0)
common/common_rl/common.h (+171/-0)
common/common_rl/common_rl_test.cpp (+101/-0)
common/confreader/Makefile (+38/-0)
common/confreader/confreader.cpp (+226/-0)
common/confreader/confreader.h (+287/-0)
common/confreader/conftest.cpp (+129/-0)
common/confreader/test.config (+27/-0)
common/logger/Makefile (+42/-0)
common/logger/log_setup.cpp (+43/-0)
common/logger/log_setup.h (+30/-0)
common/logger/log_test.cpp (+46/-0)
common/plugin_loader/Makefile (+0/-29)
common/plugin_loader/doc/plugins.xmi (+0/-339)
common/plugin_loader/plugin_manager.cpp (+0/-127)
common/plugin_loader/plugin_manager.h (+0/-194)
common/plugin_loader/plugin_wrapper.cpp (+0/-146)
common/plugin_loader/plugin_wrapper.h (+0/-207)
common/plugin_loader/test/Makefile (+0/-13)
common/plugin_loader/test/plugintest.cpp (+0/-12)
common/point/Makefile (+30/-13)
common/point/common_test.cpp (+99/-44)
common/point/triad.h (+54/-27)
common/serializer/Makefile (+36/-0)
common/serializer/serializer.cpp (+43/-0)
common/serializer/serializer.h (+50/-0)
common/serializer/serializer_test.cpp (+56/-0)
common/singleton/Makefile (+0/-18)
common/singleton/singleton.h (+0/-110)
common/singleton/singleton_test.cpp (+0/-32)
common/sockets/Makefile (+38/-0)
common/sockets/base_socket.cpp (+853/-0)
common/sockets/base_socket.h (+588/-0)
common/sockets/socket_test.cpp (+200/-0)
common/threads/Makefile (+36/-0)
common/threads/base_thread.cpp (+497/-0)
common/threads/base_thread.h (+627/-0)
common/threads/tests/cond_var.h (+124/-0)
common/threads/tests/general.h (+194/-0)
common/threads/tests/loop_counter.h (+76/-0)
common/threads/thread_test.cpp (+77/-0)
common/timer/Makefile (+36/-147)
common/timer/hires_timer.cpp (+174/-0)
common/timer/hires_timer.h (+131/-0)
common/timer/nrtb_timer.cpp (+0/-158)
common/timer/nrtb_timer.h (+0/-115)
common/timer/timer_test.cpp (+59/-27)
common/transceiver/Makefile (+31/-0)
common/transceiver/transceiver.cpp (+140/-0)
common/transceiver/transceiver.h (+276/-0)
common/transceiver/transceiver_test.cpp (+145/-0)
common/work_queue_thread/Makefile (+0/-144)
common/work_queue_thread/controlled_wqt.h (+0/-202)
common/work_queue_thread/work_queue_thread.h (+0/-248)
common/work_queue_thread/wqt_tester.cpp (+0/-154)
To merge this branch: bzr merge lp:~fpstovall/nrtb/cpp_common
Reviewer Review Type Date Requested Status
DougPiranha (community) process control Approve
George Jordan functional review for merge Approve
Rick Stovall merge test Approve
Aron Boyette Pending
jdrakey Pending
Review via email: mp+72827@code.launchpad.net

Commit message

C++ common libraries for alpha development.

Description of the change

I believe the expectations for all the C++ common libraries for the Alpha phase have been met at this time. This branch is ready for code review for merge to the alpha main branch.

To post a comment you must log in.
Revision history for this message
Rick Stovall (fpstovall) wrote :

I took the liberty of adding the the team members who can do code reviews to this review record. Have at it guys. If you find any problems, create a new bug and assign it to me for resolution.

Revision history for this message
Rick Stovall (fpstovall) :
review: Abstain (can not review)
Revision history for this message
Rick Stovall (fpstovall) wrote :

I conducted a test merge into a copy of the alpha branch. The merge completed automatically with no manual overrides required. I reviewed the change list and found only the expected changes. I then went to the common directory and ran make, piping the build and unit test output to a file. Careful review of the file showed all builds and all unit tests completed successfully.

In the absence of other reviews, this will constitute sufficient review and approval to merge the cpp_common branch into the alpha main branch.

review: Approve (merge test)
Revision history for this message
Aron Boyette (aron-carolina) wrote :

I'm still going to review out it. Are you available Tuesday to discuss
findings?
On Sep 4, 2011 8:33 PM, "Rick Stovall" <email address hidden> wrote:
> Review: Approve merge test
> I conducted a test merge into a copy of the alpha branch. The merge
completed automatically with no manual overrides required. I reviewed the
change list and found only the expected changes. I then went to the common
directory and ran make, piping the build and unit test output to a file.
Careful review of the file showed all builds and all unit tests completed
successfully.
>
> In the absence of other reviews, this will constitute sufficient review
and approval to merge the cpp_common branch into the alpha main branch.
> --
> https://code.launchpad.net/~fpstovall/nrtb/cpp_common/+merge/72827
> You are requested to review the proposed merge of
lp:~fpstovall/nrtb/cpp_common into lp:nrtb.

Revision history for this message
Rick Stovall (fpstovall) wrote :

Aron (and the rest of the team), while you are certainly welcome to look at any code set at any time, we need to get this code into the main tree to enable further work on the simulation engine and the data broker. At this point, this is a blocker for work on those components. It's been up for review now for 10 days and that seems a reasonable amount of time to hold up things waiting on review.

Please take a look at the code at your leisure and create bugs for any issues you may find. It's only alpha code, so there are sure to be some! In the meanwhile, unless some breaking issue is found by tonight, I'll move the branch forward to the main stream so that we can continue work on the rest of components needed for the alpha milestone.

Revision history for this message
George Jordan (gsjordanc) wrote :

Checked out functional build of cpp_common changes and fixes. Passed functional build test and appears by default to be ready to merge. Will continue to validate however merge may proceed, no apparent discreapancies or problem that would prevent this merge.

review: Approve (functional review for merge)
Revision history for this message
DougPiranha (dougpirahna) wrote :

Rick and George say everything is okay, so WTF. Damn the torpedoes, full speed ahead.

Revision history for this message
DougPiranha (dougpirahna) wrote :

Rick spanked my hand. (I liked it.) He said I did not do it right. Is this better?

review: Approve (process control)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'GPB_proto/ack_nak.proto'
2--- GPB_proto/ack_nak.proto 2010-01-14 02:24:25 +0000
3+++ GPB_proto/ack_nak.proto 2011-08-25 04:57:16 +0000
4@@ -9,6 +9,9 @@
5 // in a channel wrapper message.
6
7 // return on of these to ack the recept of each error free message.
8+
9+package nrtb_msg;
10+
11 message message_ack {
12 required uint32 msg_uid = 1;
13 }
14
15=== modified file 'GPB_proto/physics_common.proto'
16--- GPB_proto/physics_common.proto 2010-01-14 02:24:25 +0000
17+++ GPB_proto/physics_common.proto 2011-08-25 04:57:16 +0000
18@@ -11,6 +11,8 @@
19 // meters for distance, meters/sec for velocity, radians for attitude,
20 // and radians/sec for rotational velocity.
21
22+package nrtb_msg;
23+
24 message triplet {
25 required double x = 1;
26 required double y = 2;
27
28=== modified file 'GPB_proto/sim_obj_tq_update.proto'
29--- GPB_proto/sim_obj_tq_update.proto 2010-01-14 02:24:25 +0000
30+++ GPB_proto/sim_obj_tq_update.proto 2011-08-25 04:57:16 +0000
31@@ -8,6 +8,8 @@
32 // Note: these are never sent bare.. they are always payloads
33 // in a channel wrapper message.
34
35+package nrtb_msg;
36+
37 import "physics_common.proto";
38
39 // This message contains all the information required to report the
40
41=== modified file 'GPB_proto/sim_to_db_wrapper.proto'
42--- GPB_proto/sim_to_db_wrapper.proto 2010-01-14 02:24:25 +0000
43+++ GPB_proto/sim_to_db_wrapper.proto 2011-08-25 04:57:16 +0000
44@@ -7,6 +7,8 @@
45 // Note: The message defined here is a "channel wrapper", a container for
46 // all messages from the simulation engine to the data broker.
47
48+package nrtb_msg;
49+
50 import "ack_nak.proto";
51 import "sim_obj_tq_update.proto";
52
53
54=== added directory 'common/GPB'
55=== added file 'common/GPB/Makefile'
56--- common/GPB/Makefile 1970-01-01 00:00:00 +0000
57+++ common/GPB/Makefile 2011-08-25 04:57:16 +0000
58@@ -0,0 +1,34 @@
59+#***********************************************
60+#This file is part of the NRTB project (https://launchpad.net/nrtb).
61+#
62+# NRTB is free software: you can redistribute it and/or modify
63+# it under the terms of the GNU General Public License as published by
64+# the Free Software Foundation, either version 3 of the License, or
65+# (at your option) any later version.
66+#
67+# NRTB is distributed in the hope that it will be useful,
68+# but WITHOUT ANY WARRANTY; without even the implied warranty of
69+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
70+# GNU General Public License for more details.
71+#
72+# You should have received a copy of the GNU General Public License
73+# along with NRTB. If not, see <http://www.gnu.org/licenses/>.
74+#
75+#***********************************************
76+
77+proto=../../GPB_proto
78+
79+lib: lib/nrtb_gpb.a
80+ @echo "GPB lib build complete."
81+
82+lib/nrtb_gpb.a:
83+ @protoc -I=${proto} --cpp_out=cpp_src/ ${proto}/*.proto
84+ @cd obj; for file in ../cpp_src/*.cc; do g++ -c $$file; done
85+ @cp -v cpp_src/*h ../include
86+ @ar -r ../lib/nrtb_gpb.a obj/*.o
87+
88+clean:
89+ @cd cpp_src; for file in *h; do rm -vf ../../include/$$file; done
90+ @rm -vf ../lib/nrtb_gpb.a
91+ @rm -f obj/* cpp_src/*
92+ @echo "GPB cleanup complete."
93
94=== added directory 'common/GPB/cpp_src'
95=== added directory 'common/GPB/obj'
96=== modified file 'common/Makefile'
97--- common/Makefile 2010-01-14 02:24:25 +0000
98+++ common/Makefile 2011-08-25 04:57:16 +0000
99@@ -1,6 +1,27 @@
100-lib:
101+#***********************************************
102+#This file is part of the NRTB project (https://launchpad.net/nrtb).
103+#
104+# NRTB is free software: you can redistribute it and/or modify
105+# it under the terms of the GNU General Public License as published by
106+# the Free Software Foundation, either version 3 of the License, or
107+# (at your option) any later version.
108+#
109+# NRTB is distributed in the hope that it will be useful,
110+# but WITHOUT ANY WARRANTY; without even the implied warranty of
111+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
112+# GNU General Public License for more details.
113+#
114+# You should have received a copy of the GNU General Public License
115+# along with NRTB. If not, see <http://www.gnu.org/licenses/>.
116+#
117+#***********************************************
118+
119+lib: ./lib/nrtb_common.a
120+
121+./lib/nrtb_common.a:
122 @echo "============= building common libs ==============="
123 @make action=lib doit
124+ @ar -r ./lib/nrtb_common.a ./obj/*.o
125 @echo "============= common libs complete ==============="
126
127 modules:
128@@ -11,12 +32,18 @@
129 clean:
130 @echo "============= cleaning common libs ==============="
131 @make action=clean doit
132- @rm -fv ./obj/*
133+ @rm -fv ./obj/* ./lib/*
134 @echo "========== common lib cleanup complete ==========="
135
136 doit:
137+ @cd common_rl; make ${action}
138 @cd point; make ${action}
139 @cd timer; make ${action}
140- @cd work_queue_thread; make ${action}
141+ @cd threads; make ${action}
142+ @cd sockets; make ${action}
143+ @cd serializer; make ${action}
144 @cd singleton; make ${action}
145- @cd plugin_loader; make ${action}
146+ @cd logger; make ${action}
147+ @cd confreader; make ${action}
148+ @cd GPB; make ${action}
149+ @cd transceiver; make ${action}
150
151=== added directory 'common/common_rl'
152=== added file 'common/common_rl/Makefile'
153--- common/common_rl/Makefile 1970-01-01 00:00:00 +0000
154+++ common/common_rl/Makefile 2011-08-25 04:57:16 +0000
155@@ -0,0 +1,36 @@
156+#***********************************************
157+#This file is part of the NRTB project (https://launchpad.net/nrtb).
158+#
159+# NRTB is free software: you can redistribute it and/or modify
160+# it under the terms of the GNU General Public License as published by
161+# the Free Software Foundation, either version 3 of the License, or
162+# (at your option) any later version.
163+#
164+# NRTB is distributed in the hope that it will be useful,
165+# but WITHOUT ANY WARRANTY; without even the implied warranty of
166+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
167+# GNU General Public License for more details.
168+#
169+# You should have received a copy of the GNU General Public License
170+# along with NRTB. If not, see <http://www.gnu.org/licenses/>.
171+#
172+#***********************************************
173+
174+lib: common_rl_test
175+ @./common_rl_test
176+ @cp -v common.h ../include
177+ @cp -v common.o ../obj
178+ @echo build complete
179+
180+common.o: common.h common.cpp Makefile
181+ @rm -f common.o
182+ g++ -c -O3 common.cpp
183+
184+common_rl_test: common.o common_rl_test.cpp
185+ @rm -f common_rl_test
186+ g++ -c common_rl_test.cpp
187+ g++ -o common_rl_test common_rl_test.o common.o
188+
189+clean:
190+ @rm -rvf *.o ../include/common.h ../obj/common.o common_rl_test
191+ @echo all objects and executables have been erased.
192
193=== added file 'common/common_rl/common.cpp'
194--- common/common_rl/common.cpp 1970-01-01 00:00:00 +0000
195+++ common/common_rl/common.cpp 2011-08-25 04:57:16 +0000
196@@ -0,0 +1,274 @@
197+/***********************************************
198+ T his file is part of the NRTB project (https://*launchpad.net/nrtb).
199+
200+ NRTB is free software: you can redistribute it and/or modify
201+ it under the terms of the GNU General Public License as published by
202+ the Free Software Foundation, either version 3 of the License, or
203+ (at your option) any later version.
204+
205+ NRTB is distributed in the hope that it will be useful,
206+ but WITHOUT ANY WARRANTY; without even the implied warranty of
207+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
208+ GNU General Public License for more details.
209+
210+ You should have received a copy of the GNU General Public License
211+ along with NRTB. If not, see <http://www.gnu.org/licenses/>.
212+
213+ **********************************************/
214+
215+#include <stdlib.h>
216+#include <iostream>
217+#include <math.h>
218+#include <time.h>
219+#include "common.h"
220+
221+using namespace std;
222+
223+namespace nrtb
224+{
225+
226+base_exception::base_exception()
227+{
228+ ctime = time(NULL);
229+};
230+
231+base_exception::base_exception(const string & text)
232+{
233+ ctime = time(NULL);
234+ _text = text;
235+};
236+
237+void base_exception::store(const string & s)
238+{
239+ _text = s;
240+};
241+
242+string base_exception::comment()
243+{
244+ return _text;
245+};
246+
247+unsigned long int base_exception::creation_time()
248+{
249+ return ctime;
250+};
251+
252+const string __ricks_handy_upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
253+const string __ricks_handy_lower = "abcdefghijklmnopqrstuvwxyz";
254+
255+string changecase(const string &s,const string &upper, const string &lower)
256+{
257+ try
258+ {
259+ string returnme = "";
260+ for (int i = 0; i < s.size(); i++)
261+ {
262+ unsigned long int loc = lower.find(s[i]);
263+ if (loc == string::npos)
264+ {
265+ returnme += s[i];
266+ }
267+ else
268+ {
269+ returnme += upper[loc];
270+ };
271+ };
272+ return returnme;
273+ }
274+ catch (...)
275+ {
276+ throw translate_exception();
277+ };
278+};
279+
280+string upcase(const string &s)
281+{
282+ return changecase(s,__ricks_handy_upper,__ricks_handy_lower);
283+};
284+
285+string downcase(const string &s)
286+{
287+ return changecase(s,__ricks_handy_lower,__ricks_handy_upper);
288+};
289+
290+
291+const string __ricks_handy_hexits = "0123456789ABCDEF";
292+
293+string gsub(const string & target, const string & findme, const string & putme)
294+{
295+ // error checking
296+ if (findme.empty() || target.empty())
297+ {
298+ throw gsub_exception();
299+ };
300+ string returnme = "";
301+ unsigned long int okay_through = 0;
302+ unsigned long int step = findme.length();
303+ unsigned long int where = target.find(findme,okay_through);
304+ while (where != string::npos)
305+ {
306+ returnme += target.substr(okay_through,where-okay_through) + putme;
307+ okay_through = where + step;
308+ where = target.find(findme,okay_through);
309+ };
310+ returnme += target.substr(okay_through);
311+ return returnme;
312+};
313+
314+strlist split(const string & source, const char token)
315+{
316+ strlist returnme;
317+ returnme.clear();
318+ if (source.size() > 0)
319+ {
320+ unsigned long int loc;
321+ unsigned long int processed = 0;
322+ try
323+ {
324+ loc = source.find(token,processed);
325+ while (loc != string::npos)
326+ {
327+ returnme.push_back(source.substr(processed,loc-processed));
328+ processed = loc + 1;
329+ loc = source.find(token,processed);
330+ }
331+ returnme.push_back(source.substr(processed));
332+ }
333+ catch (...)
334+ {
335+ throw split_exception();
336+ };
337+ };
338+ return returnme;
339+};
340+
341+string trim(std::string s)
342+{
343+ const string ws = "\t\n ";
344+ unsigned long int where = s.find_first_not_of(ws);
345+ if (where != string::npos)
346+ {
347+ s.erase(0,where);
348+ };
349+ where = s.find_last_not_of(ws);
350+ if (where != string::npos)
351+ {
352+ s.erase(where+1);
353+ };
354+ return s;
355+};
356+
357+string mconvert(const string &s)
358+{
359+ /* This function is designed to escape strings destined for
360+ * use in SQL queries and the like. Specifically, the following
361+ * is done to the string passed in:
362+ * 1. "\" is replaced with "\\"
363+ * 2. "'" is replaced with "\'"
364+ * 3. """ (double quote) is replaced with "\""
365+ * 4. 0x00 is replaced with "\"+0x00.
366+ */
367+ string returnme = "";
368+ if (s.length() > 0)
369+ {
370+ returnme = gsub(s,"\\","\\\\");
371+ returnme = gsub(returnme,"'", "\\'");
372+ returnme = gsub(returnme,"\"","\\\"");
373+ // special handling is required to make strings including
374+ // 0x00; this is the kludge I found to work at 2200 tonight.
375+ string findme = " "; findme[0] = 0;
376+ returnme = gsub(returnme,findme,"\\0");
377+ };
378+ return returnme;
379+};
380+
381+string dateflip(string date, const string & sep)
382+{
383+ string out;
384+ try
385+ {
386+ strlist temp = split(date,'-');
387+ out = temp[1]+ sep + temp[2] + sep + temp[0];
388+ }
389+ catch (...)
390+ {
391+ throw dateflip_exception();
392+ };
393+ return out;
394+}; // string dateflip
395+
396+string http_hextochar(string s)
397+{
398+ try
399+ {
400+ s = upcase(s);
401+ unsigned char v = (16 * __ricks_handy_hexits.find(s[0]))
402+ + __ricks_handy_hexits.find(s[1]);
403+ return s = v;
404+ }
405+ catch (...)
406+ {
407+ throw hextrans_exception();
408+ };
409+}; // string hextochar
410+
411+string http_chartohex(const string &s)
412+{
413+ string out;
414+ try
415+ {
416+ for (long int i=0; i < s.length() ; i++ ) {
417+ unsigned char v = s[i];
418+ div_t hexval = div(v,16);
419+ out += __ricks_handy_hexits[hexval.quot];
420+ out += __ricks_handy_hexits[hexval.rem];
421+ }; /* endfor */
422+ }
423+ catch (...)
424+ {
425+ throw hextrans_exception();
426+ };
427+ return out;
428+};// string chartohex()
429+
430+string http_enhex(const string & s)
431+{
432+ string out;
433+ try
434+ {
435+ for (long int i=0; i < s.length() ; i++ ) {
436+ unsigned char v = s[i];
437+ div_t hexval = div(v,16);
438+ out += "%";
439+ out += __ricks_handy_hexits[hexval.quot];
440+ out += __ricks_handy_hexits[hexval.rem];
441+ }; /* endfor */
442+ }
443+ catch (...)
444+ {
445+ throw hextrans_exception();
446+ };
447+ return out;
448+}; // string enhex()
449+
450+string http_unhex(string s)
451+{
452+ try
453+ {
454+ while (s.find('%') != string::npos)
455+ {
456+ int where = s.find('%');
457+ string hexchar = s.substr(where+1,2);
458+ s.erase(where,3);
459+ s.insert(where,http_hextochar(hexchar));
460+ }; /* endwhile */
461+ }
462+ catch (...)
463+ {
464+ throw hextrans_exception();
465+ };
466+ return s;
467+};// string unhex()
468+
469+
470+} // namespace nrtb
471
472=== added file 'common/common_rl/common.h'
473--- common/common_rl/common.h 1970-01-01 00:00:00 +0000
474+++ common/common_rl/common.h 2011-08-25 04:57:16 +0000
475@@ -0,0 +1,171 @@
476+/***********************************************
477+ T his file is part of the NRTB project (https://*launchpad.net/nrtb).
478+
479+ NRTB is free software: you can redistribute it and/or modify
480+ it under the terms of the GNU General Public License as published by
481+ the Free Software Foundation, either version 3 of the License, or
482+ (at your option) any later version.
483+
484+ NRTB is distributed in the hope that it will be useful,
485+ but WITHOUT ANY WARRANTY; without even the implied warranty of
486+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
487+ GNU General Public License for more details.
488+
489+ You should have received a copy of the GNU General Public License
490+ along with NRTB. If not, see <http://www.gnu.org/licenses/>.
491+
492+ **********************************************/
493+
494+// prevent multiple definitions
495+#ifndef __ga_common_h
496+#define __ga_common_h 1
497+
498+//#include <stream.h>
499+#include <string>
500+#include <map>
501+#include <vector>
502+
503+namespace nrtb
504+{
505+
506+// throwable exception classes
507+
508+/** Provides a base exception class for use in HCS developed programs.
509+ **
510+ ** Usage: Inherit your exception classes from this class. When throwing a
511+ ** derived exception you'll have the option of either instanciating the
512+ ** exception with a comment or not; in any case the time the exception was
513+ ** instanciated will be recorded. Later, when catching the exception you can
514+ ** get the time the exception was created and any text the thrower may have
515+ ** provided.
516+ **/
517+ class base_exception: public std::exception
518+ {
519+ protected:
520+ unsigned long int ctime;
521+ std::string _text;
522+ public:
523+ /** Default constructor.
524+ **
525+ ** Creates an nrtb_exception recording it's creation time but without
526+ ** a comment string.
527+ **/
528+ base_exception();
529+ /** Constructs with a comment string.
530+ **
531+ ** Creates an nrtb_exception recording it's creation time and storing the
532+ ** provided string "text" for recall later via the comment method.
533+ **
534+ ** This version takes an ISO standard C++ string.
535+ **/
536+ base_exception(const std::string & text);
537+ /// NOP virtual distructor for safe inheritance
538+ virtual ~base_exception() throw() {};
539+ /** Stores a comment string.
540+ **/
541+ void store(const std::string & s);
542+ /** Returns the value stored at exception creation.
543+ **/
544+ std::string comment();
545+ /** Returns the unix time the exception was created.
546+ **/
547+ unsigned long int creation_time();
548+};
549+
550+// Thrown by gsub() in cases of unexpected error.
551+class gsub_exception: public nrtb::base_exception {};
552+// Thrown by split() in cases of unexpected error.
553+class split_exception: public nrtb::base_exception {};
554+// Thrown by dateflip in cases of unexpected error.
555+class dateflip_exception: public nrtb::base_exception {};
556+// Thrown by upcase() and downcase() in cases of unexpected error.
557+class translate_exception: public nrtb::base_exception {};
558+// Thrown by http_* functions in cases of unexpected error.
559+class hextrans_exception: public nrtb::base_exception {};
560+// Thrown by the biased_rand* functions in cases of unexpected error.
561+class rand_exception: public nrtb::base_exception {};
562+
563+// handy commonly used maps
564+/// A map of ints keyed by ints.
565+typedef std::map<int,int> num_map;
566+/// A map of ints keyed by strings.
567+typedef std::map<std::string,int> string_map;
568+
569+/// the return type for split.
570+typedef std::vector<std::string> strlist;
571+
572+/** Converts the alpha components of s to all upper case.
573+ **
574+ ** May throw a nrtb::translate_exception if there is a problem.
575+ **/
576+std::string upcase(const std::string &s);
577+
578+/** Converts the alpha components of s to all lower case.
579+ **
580+ ** May throw a nrtb::translate_exception if there is a problem.
581+ **/
582+std::string downcase(const std::string &s);
583+
584+/** Replaces all instances of findme in target with putme.
585+ **
586+ ** May throw a nrtb::gsub_exception if there is a problem.
587+ **/
588+std::string gsub(const std::string & target, const std::string & findme,
589+ const std::string & putme);
590+
591+/** Splits the string source using token as a delimiter and returns
592+ ** the results in vector of strings.
593+ **
594+ ** May throw a nrtb::split_exception if there is a problem.
595+ **/
596+strlist split(const std::string & source, const char token);
597+
598+/// Performs SQL escaping on the string.
599+std::string mconvert(const std::string & s);
600+
601+/// Removes white space from both ends of a string.
602+std::string trim(std::string s);
603+
604+/** Takes an ISO standard date (YYYY-MM-DD) and returns MM-DD-YYYY.
605+ **
606+ ** May throw a nrtb::dateflip_exception if there is a problem.
607+ **/
608+std::string dateflip(std::string date, const std::string & sep="-");
609+
610+/** Takes a string representing one HTTP hex-encoded byte and returns
611+ ** the appropriate character. This will only operate on the first two
612+ ** bytes of s, and will throw a nrtb_hextrans_exception if less
613+ ** than two bytes are supplied.
614+ **
615+ ** May throw a nrtb::hextrans_exception if there is a problem.
616+ **/
617+std::string http_hextochar(std::string s);
618+
619+/** Takes a string and returns it hex-encoded (i.e. " " returns "20").
620+ **
621+ ** This function is somewhat misnamed due to hysterical reasons. In
622+ ** truth it simply returns the hex equivilent of the input. Use
623+ ** http_enhex() when you actually need valid HTTP hex encoding.
624+ ** On the other hand, this function is quite
625+ ** useful if you need to hex up a series of bytes and don't need the
626+ ** overhead of the extra byte per character of true HTTP hex encoding.
627+ **
628+ ** May throw a nrtb::hextrans_exception if there is a problem.
629+*/
630+std::string http_chartohex(const std::string &s);
631+
632+/** Takes a string and returns it in HTTP hex-encoded format (" " returns "%20").
633+ **
634+ ** May throw a nrtb::hextrans_exception if there is a problem.
635+ **/
636+std::string http_enhex(const std::string &s);
637+
638+/** Takes a string and returns it with all HTTP hex-encoded bytes changed to
639+ ** their normal single byte representation.
640+ **
641+ ** May throw a nrtb::hextrans_exception if there is a problem.
642+ **/
643+std::string http_unhex(std::string s);
644+
645+} // namespace nrtb
646+#endif /* __ga_common_h */
647
648=== added file 'common/common_rl/common_rl_test.cpp'
649--- common/common_rl/common_rl_test.cpp 1970-01-01 00:00:00 +0000
650+++ common/common_rl/common_rl_test.cpp 2011-08-25 04:57:16 +0000
651@@ -0,0 +1,101 @@
652+/***********************************************
653+ T his file is part of the NRTB project (https://*launchpad.net/nrtb).
654+
655+ NRTB is free software: you can redistribute it and/or modify
656+ it under the terms of the GNU General Public License as published by
657+ the Free Software Foundation, either version 3 of the License, or
658+ (at your option) any later version.
659+
660+ NRTB is distributed in the hope that it will be useful,
661+ but WITHOUT ANY WARRANTY; without even the implied warranty of
662+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
663+ GNU General Public License for more details.
664+
665+ You should have received a copy of the GNU General Public License
666+ along with NRTB. If not, see <http://www.gnu.org/licenses/>.
667+
668+ **********************************************/
669+
670+#include "common.h"
671+#include <iostream>
672+
673+using namespace std;
674+
675+int report_test(const string banner, bool test)
676+{
677+ string result;
678+ int returnme = 0;
679+ if (test)
680+ {
681+ result = "PASSED";
682+ }
683+ else
684+ {
685+ result = "FAILED";
686+ returnme = 1;
687+ };
688+ cout << "\t" << banner << ": " << result << endl;
689+ return returnme;
690+};
691+
692+int main()
693+{
694+ cout << "=== Starting nrtb::common_rl unit test ===" << endl;
695+ int returnme = 0;
696+ string tstr = "MiXeDcAsE";
697+
698+ returnme += report_test(
699+ "nrtb::upcase()",
700+ nrtb::upcase(tstr) == "MIXEDCASE");
701+
702+ returnme += report_test(
703+ "nrtb::downcase()",
704+ nrtb::downcase(tstr) == "mixedcase");
705+
706+ returnme += report_test(
707+ "nrtb::gsub()",
708+ nrtb::gsub(tstr, "cAsE", " frogs") == "MiXeD frogs");
709+
710+ // split() testing
711+ nrtb::strlist tokens = nrtb::split("this is a test",' ');
712+ bool faults = tokens.size() == 4;
713+ faults = faults or (tokens[0] == "this");
714+ faults = faults or (tokens[0] == "is");
715+ faults = faults or (tokens[0] == "a");
716+ faults = faults or (tokens[0] == "test");
717+ returnme += report_test(
718+ "nrtb::split()",
719+ faults);
720+
721+ string tchar = " "; tchar[0] = 0;
722+ returnme += report_test(
723+ "nrtb::mconvert()",
724+ nrtb::mconvert("\\ \" '"+tchar) == "\\\\ \\\" \\\'\\0");
725+
726+ returnme += report_test(
727+ "nrtb::trim()",
728+ nrtb::trim("\t"+tstr+" ") == tstr);
729+
730+ returnme += report_test(
731+ "nrtb::dateflip()",
732+ nrtb::dateflip("2011-07-21") == "07-21-2011");
733+
734+ returnme += report_test(
735+ "nrtb::http_hextochar()",
736+ nrtb::http_hextochar("20") == " ");
737+
738+ returnme += report_test(
739+ "nrtb::http_chartohex()",
740+ nrtb::http_chartohex(tstr) == "4D6958654463417345");
741+
742+ returnme += report_test(
743+ "nrtb::http_enhex()",
744+ nrtb::http_enhex(tstr) == "%4D%69%58%65%44%63%41%73%45");
745+
746+ returnme += report_test(
747+ "nrtb::http_unhex()",
748+ nrtb::http_unhex("%4D%69%58%65%44%63%41%73%45") == tstr);
749+
750+ cout << "=== nrtb::common_rl unit test complete ===" << endl;
751+ return returnme;
752+};
753\ No newline at end of file
754
755=== added directory 'common/confreader'
756=== added file 'common/confreader/Makefile'
757--- common/confreader/Makefile 1970-01-01 00:00:00 +0000
758+++ common/confreader/Makefile 2011-08-25 04:57:16 +0000
759@@ -0,0 +1,38 @@
760+#***********************************************
761+#This file is part of the NRTB project (https://launchpad.net/nrtb).
762+#
763+# NRTB is free software: you can redistribute it and/or modify
764+# it under the terms of the GNU General Public License as published by
765+# the Free Software Foundation, either version 3 of the License, or
766+# (at your option) any later version.
767+#
768+# NRTB is distributed in the hope that it will be useful,
769+# but WITHOUT ANY WARRANTY; without even the implied warranty of
770+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
771+# GNU General Public License for more details.
772+#
773+# You should have received a copy of the GNU General Public License
774+# along with NRTB. If not, see <http://www.gnu.org/licenses/>.
775+#
776+#***********************************************
777+
778+lib: conftest
779+ @rm -f conf_test.log
780+ @./conftest test=1 test2-2 test2=71.837486 test3="jack danials" --doit
781+ @grep "Run Complete" conf_test.log
782+ @cp -v confreader.h ../include
783+ @cp -v confreader.o ../obj
784+ @echo build complete
785+
786+confreader.o: confreader.h confreader.cpp Makefile
787+ @rm -f confreader.o
788+ g++ -c confreader.cpp -I../include
789+
790+conftest: confreader.o conftest.cpp
791+ @rm -f conftest
792+ g++ -c conftest.cpp -I../include
793+ g++ -o conftest conftest.o confreader.o ../obj/common.o ../obj/log_setup.o ../obj/base_thread.o -lpthread -lPocoFoundation -lPocoUtil
794+
795+clean:
796+ @rm -rvf *.o conftest ../include/confreader.h ../obj/confreader.o conf_test.log
797+ @echo all objects and executables have been erased.
798
799=== added file 'common/confreader/confreader.cpp'
800--- common/confreader/confreader.cpp 1970-01-01 00:00:00 +0000
801+++ common/confreader/confreader.cpp 2011-08-25 04:57:16 +0000
802@@ -0,0 +1,226 @@
803+/***********************************************
804+ This file is part of the NRTB project (https://*launchpad.net/nrtb).
805+
806+ NRTB is free software: you can redistribute it and/or modify
807+ it under the terms of the GNU General Public License as published by
808+ the Free Software Foundation, either version 3 of the License, or
809+ (at your option) any later version.
810+
811+ NRTB is distributed in the hope that it will be useful,
812+ but WITHOUT ANY WARRANTY; without even the implied warranty of
813+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
814+ GNU General Public License for more details.
815+
816+ You should have received a copy of the GNU General Public License
817+ along with NRTB. If not, see <http://www.gnu.org/licenses/>.
818+
819+**********************************************/
820+
821+// see confreader.h for documentation
822+
823+#include "confreader.h"
824+#include <fstream>
825+#include <iostream>
826+#include <common.h>
827+#include "Poco/Logger.h"
828+
829+using namespace std;
830+using namespace nrtb;
831+
832+const std::string logname = "conf_reader";
833+
834+namespace nrtb
835+{
836+
837+conf_reader::conf_reader()
838+{
839+ Poco::Logger& logger = Poco::Logger::get(logname);
840+ logger.information("conf_reader instanciated.");
841+};
842+
843+conf_reader::~conf_reader() {};
844+
845+unsigned int conf_reader::read(const std::string & _filename, bool _clear)
846+{
847+ Poco::Logger& logger = Poco::Logger::get(logname);
848+ logger.information("Reading from \"" + _filename + "\".");
849+ if (_filename != "") { filename = _filename; };
850+ if (filename != "")
851+ {
852+ try
853+ {
854+ ifstream cfile(filename.c_str());
855+ if (!cfile) throw base_exception();
856+ if (_clear) values.clear();
857+ // read the file line by line, ignoring comments.
858+ char inbuff[16*1024];
859+ while (cfile)
860+ {
861+ cfile.getline(inbuff, 16*1024);
862+ string in = inbuff;
863+ // truncate at the start of a comment.
864+ unsigned long int where = in.find("#");
865+ while (where != string::npos)
866+ {
867+ if (in[where-1] == '\\')
868+ {
869+ // comment char was escaped.. ignore.
870+ where = in.find("#",where+1);
871+ }
872+ else
873+ {
874+ // truncate the string at this point.
875+ in.erase(where);
876+ where = string::npos;
877+ };
878+ };
879+ // see if we can parse what's left.
880+ in = trim(in);
881+ unsigned long int split_point = in.find_first_of("\t ");
882+ if (split_point != string::npos)
883+ {
884+ // okay.. get the fields.
885+ pair arg;
886+ arg.first = gsub(trim(in.substr(0,split_point)),"\\#","#");
887+ arg.second = gsub(trim(in.substr(split_point)),"\\#","#");
888+ // is this an include directive?
889+ if (arg.first == "*INCLUDE")
890+ {
891+ read(arg.second,false);
892+ }
893+ else if (arg.first != "")
894+ {
895+ values.insert(arg);
896+ };
897+ };
898+ };
899+ }
900+ catch (...)
901+ {
902+ logger.warning("Problems reading configuration file \""
903+ + filename + "\"; data may be incomplete.");
904+ }
905+ };
906+ return values.size();
907+};
908+
909+unsigned int conf_reader::read(int argc, char * argv[],
910+ const string & _filename)
911+{
912+ Poco::Logger& logger = Poco::Logger::get(logname);
913+ logger.information("Reading from command line.");
914+ clear();
915+ filename = _filename;
916+ value_list_type cvars;
917+ // read values from the command line first.
918+ for (int i = 0; i < argc; i++)
919+ {
920+ string instring = argv[i];
921+ if (i == 0)
922+ {
923+ instring = "__exec_name="+instring;
924+ };
925+ strlist t = split(instring,'=');
926+ if (t.size() > 0)
927+ {
928+ // build the new insert pair;
929+ pair newval;
930+ newval.first = t[0];
931+ // assemble the value
932+ // (allows for including "=" in the argument)
933+ for (unsigned int l = 1; l < t.size(); l++)
934+ {
935+ newval.second += t[l];
936+ if (l < (t.size() -1) )
937+ {
938+ newval.second += "=";
939+ };
940+ };
941+ // store this in the list
942+ trim(newval.first);
943+ trim(newval.second);
944+ cvars.insert(newval);
945+ // is this a config file name?
946+ if (newval.first == "configfile")
947+ {
948+ filename = newval.second;
949+ };
950+ };
951+ }; // read the command line arguments.
952+ // read the file args if any.
953+ read(filename,false);
954+ // override the first instance of any value found in configs
955+ // or insert as appropriate.
956+ iterator c = cvars.begin();
957+ iterator e = cvars.end();
958+ while (c != e)
959+ {
960+ iterator here = values.find(c->first);
961+ if (here != values.end())
962+ {
963+ here->second = c->second;
964+ }
965+ else
966+ {
967+ values.insert(*c);
968+ };
969+ c++;
970+ };
971+ std::stringstream message;
972+ message << "Read " << values.size() << " parameters.";
973+ logger.information(message.str());
974+ return values.size();
975+};
976+
977+void conf_reader::clear()
978+{
979+ values.clear();
980+};
981+
982+conf_reader::iterator conf_reader::begin()
983+{
984+ return values.begin();
985+};
986+
987+conf_reader::iterator conf_reader::end()
988+{
989+ return values.end();
990+};
991+
992+bool conf_reader::empty()
993+{
994+ return values.empty();
995+};
996+
997+unsigned int conf_reader::size()
998+{
999+ return values.size();
1000+};
1001+
1002+strlist conf_reader::all(const std::string & key)
1003+{
1004+ strlist returnme;
1005+ iterator current = values.find(key);
1006+ iterator e = values.end();
1007+ while ((current != e) && (current->first == key))
1008+ {
1009+ returnme.push_back(current->second);
1010+ current++;
1011+ };
1012+ return returnme;
1013+};
1014+
1015+string conf_reader::operator [] (const std::string & key)
1016+{
1017+ iterator res = values.find(key);
1018+ string returnme = "";
1019+ if (res != values.end()) returnme = res->second;
1020+ return returnme;
1021+};
1022+
1023+bool conf_reader::exists(const std::string & key)
1024+{
1025+ return (values.find(key) != values.end());
1026+};
1027+
1028+} // namespace nrtb
1029
1030=== added file 'common/confreader/confreader.h'
1031--- common/confreader/confreader.h 1970-01-01 00:00:00 +0000
1032+++ common/confreader/confreader.h 2011-08-25 04:57:16 +0000
1033@@ -0,0 +1,287 @@
1034+/***********************************************
1035+ This file is part of the NRTB project (https://*launchpad.net/nrtb).
1036+
1037+ NRTB is free software: you can redistribute it and/or modify
1038+ it under the terms of the GNU General Public License as published by
1039+ the Free Software Foundation, either version 3 of the License, or
1040+ (at your option) any later version.
1041+
1042+ NRTB is distributed in the hope that it will be useful,
1043+ but WITHOUT ANY WARRANTY; without even the implied warranty of
1044+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1045+ GNU General Public License for more details.
1046+
1047+ You should have received a copy of the GNU General Public License
1048+ along with NRTB. If not, see <http://www.gnu.org/licenses/>.
1049+
1050+ **********************************************/
1051+
1052+#ifndef ricklib_confreader_h
1053+#define ricklib_confreader_h
1054+
1055+#include <string.h>
1056+#include <map>
1057+#include <vector>
1058+#include <string>
1059+#include <fstream>
1060+#include <boost/lexical_cast.hpp>
1061+#include <singleton.h>
1062+
1063+namespace nrtb
1064+{
1065+
1066+typedef std::vector<std::string> strlist;
1067+
1068+/** Reads command line and configuration file information.
1069+ **
1070+ ** For this NRTB implementation, this class is implemented as
1071+ ** a singleton.
1072+ **
1073+ ** Values read are stored in a multimap of name/value pairs and
1074+ ** may be accessed via provided iterators, or directly via the
1075+ ** [] operator, all(), get<T>() and getall<T>() methods. Automatic
1076+ ** handling of include files and comments is provided as well. The
1077+ ** get<>() and getall<>() template methods provide easy and complete
1078+ ** access to all types that have the ">>" stream operator
1079+ ** defined, including all the C++ standard types.
1080+ **/
1081+class conf_reader
1082+{
1083+ private:
1084+ typedef std::multimap<std::string,std::string> value_list_type;
1085+ value_list_type values;
1086+ std::string filename;
1087+ protected:
1088+ /** Reads and parses a configuration file.
1089+ **
1090+ ** Returns the number of values stored.
1091+ **
1092+ ** The optional parameter _clear when true clears the currently
1093+ ** stored list of values. if false the new values read will be added
1094+ ** to the existing list.
1095+ **
1096+ ** If the file named can not be processed completely, a warning
1097+ ** message is published to cerr.
1098+ **
1099+ ** Configuration files are defined as follows.
1100+ **
1101+ ** 1. Files are read line by line. No value can cross a newline
1102+ ** (and at least in this version) or include one. The good
1103+ ** news is that you are allowed up to 16k for each line.
1104+ **
1105+ ** 2. values are specifed in name/value pairs, one per line, with
1106+ ** the name first, followed by whitespace, followed by the
1107+ ** value. Values may include whitespace. All leading and trailing
1108+ ** whitespace is removed from both the name and the value.
1109+ **
1110+ ** 3. Comments start with a \# symbol; all text following a \# is
1111+ ** ignored. If you need to use \# in a name or value, escape
1112+ ** it with a backslash instead.
1113+ **
1114+ ** 4. Duplicate names are allowed.
1115+ **
1116+ ** 5. Names without values will be stored with "" as the value.
1117+ **
1118+ ** 6. A configuration file may include another configuration file
1119+ ** automatically by the use of the "*INCLUDE" reserved name.
1120+ ** When this name is found, it's value is used as the name of
1121+ ** the new file to be read.
1122+ **/
1123+ unsigned int read(const std::string & _filename = "", bool _clear=true);
1124+ public:
1125+ /// conf_reader iterator, points to a conf_reader::pair
1126+ typedef value_list_type::iterator iterator;
1127+ /// conf_reader::pair is a std::pair<string,string>
1128+ typedef std::pair<std::string,std::string> pair;
1129+ /** No argument constructor; actually calls read() without a filename.
1130+ **/
1131+ conf_reader();
1132+ /** NOP virtual destructor to allow safe inheritance.
1133+ **/
1134+ virtual ~conf_reader();
1135+ /** Reads and parses the command line and the provided file.
1136+ **
1137+ ** Returns the number of values stored. argc and argv are, of
1138+ ** course the same names you used as arguments to main(). Therefore
1139+ ** you can easily read all command line and configuration file
1140+ ** values like this:
1141+ **
1142+ ** int main(int argc, char* argv[])
1143+ **
1144+ ** {
1145+ **
1146+ ** conf_reader config;
1147+ **
1148+ ** config.read(argc,argv,"my_conf_file");
1149+ **
1150+ ** ...
1151+ **
1152+ ** }
1153+ **
1154+ ** See read(filename,_clear) for a discription of how configuration
1155+ ** files are structured and parsed. This method unconditionally
1156+ ** clears the existing value list before starting. For command line
1157+ ** arguments the following rules are true.
1158+ **
1159+ ** 1. The executable name (argv[0]) is stored as a value with the
1160+ ** name "__exec_name".
1161+ **
1162+ ** 2. Command line arguments of the form "name=value" are parsed
1163+ ** stored as named values.
1164+ **
1165+ ** 3. All other command line arguments are stored as names with
1166+ ** value = "".
1167+ **
1168+ ** 4. A command line argument of form "configfile=filename" will
1169+ ** override the filename supplied as an argument to this method.
1170+ **
1171+ ** 5. In the case of duplicate command line arguments, the last one
1172+ ** specified wins.
1173+ **
1174+ ** 6. In the case of names in the configuration file duplicating
1175+ ** names from the command line, the values from the command line
1176+ ** dominate. If there were multiple values for a given name
1177+ ** specified in the file, only the first one (the one returned by
1178+ ** the "[]" operator or get<>() method) is overridden.
1179+ **/
1180+ unsigned int read(int argc, char* argv[],
1181+ const std::string & _filename);
1182+ /// clears the name/value list.
1183+ void clear();
1184+ /// returns an iterator to the first item in the list.
1185+ iterator begin();
1186+ /// returns an iterator one past the end of the list.
1187+ iterator end();
1188+ /// True if there are no values, false otherwise.
1189+ bool empty();
1190+ /// Returns the number of values stored.
1191+ unsigned int size();
1192+ /** Returns the string value matching the supplied name.
1193+ **
1194+ ** NOTE: the use of get<T>(key) or get<T>(key,default) is preferred.
1195+ ** This method is public to allow for specialized handling in the
1196+ ** rare cases where it may be required.
1197+ **
1198+ ** If there are no matching names, "" is returned. Be aware that
1199+ ** "" is a valid value, so you can not use this to verify that
1200+ ** a given name was defined. Use exists() for that.
1201+ **/
1202+ std::string operator [] (const std::string & key);
1203+ /** Returns all values associated with the supplied name.
1204+ **
1205+ ** NOTE: the use of getall<T>(key) is preferred. This method is
1206+ ** public to allow specialized handling in rare case where it
1207+ ** may be required.
1208+ **
1209+ ** If there are no values defined the strlist will be empty.
1210+ **/
1211+ strlist all(const std::string & key);
1212+ /// True if the name exists, false otherwise.
1213+ bool exists(const std::string & key);
1214+ /** Use this to get all matching values.
1215+ **
1216+ ** Usage:
1217+ **
1218+ ** vector<type> mylist = conf_reader_object.getall<type>(key);
1219+ **
1220+ ** type can be any standard type (string, int, double, etc.) or any
1221+ ** type for which the ">>" stream operator is defined. All values
1222+ ** with matching names that can map to the requested type will be
1223+ ** returned. Any that do not map will not be returned.
1224+ **/
1225+ template < class T >
1226+ typename std::vector<T> getall(const std::string & key);
1227+ /** Use this to get the matching value.
1228+ **
1229+ ** Useage:
1230+ **
1231+ ** type myvar = get<type>(key);
1232+ **
1233+ ** type can be any standard type (string, int, double, etc.) or any
1234+ ** type for which the ">>" stream operator is defined. The return
1235+ ** value is initialized to all zeros if no matching name is found or
1236+ ** if the first value with that name does not map to the requested
1237+ ** type. For the numeric types that results in zero being returned,
1238+ ** but be aware that more complex object may be in non-sensible
1239+ ** states if they were not found or could not map. Use exists() to
1240+ ** verify the existance of a given name if needed.
1241+ **/
1242+ template < class T >
1243+ T get(const std::string & key);
1244+ /** Returns the value for the requested key, or the supplied default.
1245+ **
1246+ ** Works exactly like get<>() with the exception that if the key
1247+ ** is not found in the list, the user supplied default value is
1248+ ** returned instead of 0 or an empty string. If the value exists but
1249+ ** can not map to the requested type, 0 or an empty string is
1250+ ** returned for the standard types.
1251+ **/
1252+ template <class T>
1253+ T get(const std::string & key, const T & def);
1254+};
1255+
1256+typedef singleton<conf_reader> global_conf_reader;
1257+
1258+template < class T >
1259+ typename std::vector<T> conf_reader::getall(const std::string & key)
1260+{
1261+ strlist tvals = all(key);
1262+ std::vector<T> returnme;
1263+ if (typeid(T) == typeid(std::string))
1264+ {
1265+ // T is a std::string.. we can do this quickly.
1266+ strlist * wl = (strlist *) &returnme;
1267+ *wl = tvals;
1268+ }
1269+ else
1270+ {
1271+ // T is non-string.. will require more playing around.
1272+ unsigned int limit = tvals.size();
1273+ for (unsigned int i = 0; i < limit; i++)
1274+ {
1275+ try
1276+ {
1277+ returnme.push_back(boost::lexical_cast<T>(tvals[i]));
1278+ }
1279+ catch (...) {};
1280+ };
1281+ };
1282+ return returnme;
1283+};
1284+
1285+template < class T >
1286+ T conf_reader::get(const std::string & key)
1287+{
1288+ conf_reader & me = *this;
1289+ std::string tval = me[key];
1290+ T returnme;
1291+ // initialize the return value to nulls
1292+ // Needed for the numeric types, but bad for strings.
1293+ if (typeid(T) != typeid(std::string))
1294+ {
1295+ // null out the working area (death for strings!)
1296+ memset(&returnme,0,sizeof(T));
1297+ };
1298+ // This does appear to work for all the standard types.
1299+ if (tval != "")
1300+ {
1301+ try
1302+ {
1303+ returnme = boost::lexical_cast<T>(tval);
1304+ }
1305+ catch (...) {};
1306+ };
1307+ return returnme;
1308+};
1309+
1310+template < class T >
1311+ T conf_reader::get(const std::string & key, const T & def)
1312+{
1313+ if (exists(key)) { return get<T>(key); }
1314+ else { return def; };
1315+};
1316+
1317+}; // namespace nrtb
1318+
1319+#endif // ricklib_confreader_h
1320+
1321
1322=== added file 'common/confreader/conftest.cpp'
1323--- common/confreader/conftest.cpp 1970-01-01 00:00:00 +0000
1324+++ common/confreader/conftest.cpp 2011-08-25 04:57:16 +0000
1325@@ -0,0 +1,129 @@
1326+/***********************************************
1327+ This file is part of the NRTB project (https://*launchpad.net/nrtb).
1328+
1329+ NRTB is free software: you can redistribute it and/or modify
1330+ it under the terms of the GNU General Public License as published by
1331+ the Free Software Foundation, either version 3 of the License, or
1332+ (at your option) any later version.
1333+
1334+ NRTB is distributed in the hope that it will be useful,
1335+ but WITHOUT ANY WARRANTY; without even the implied warranty of
1336+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1337+ GNU General Public License for more details.
1338+
1339+ You should have received a copy of the GNU General Public License
1340+ along with NRTB. If not, see <http://www.gnu.org/licenses/>.
1341+
1342+ **********************************************/
1343+
1344+/* confreader test program */
1345+
1346+#include "confreader.h"
1347+#include <log_setup.h>
1348+#include <iostream>
1349+#include "Poco/Logger.h"
1350+#include "Poco/SimpleFileChannel.h"
1351+//#include "Poco/AutoPtr.h"
1352+
1353+using namespace nrtb;
1354+using namespace std;
1355+
1356+int main(int argc, char* argv[])
1357+{
1358+ bool set_if_failed = false;
1359+ setup_global_logging("conf_test.log");
1360+ Poco::Logger & log = Poco::Logger::get("conftest");
1361+ log.information("=-=-=-=-=-= conftest Init =-=-=-=-=-=-=");
1362+ global_conf_reader & config = global_conf_reader::get_instance();
1363+ try
1364+ {
1365+ log.information("Starting read");
1366+ config.read(argc,argv,"test.config");
1367+ }
1368+ catch (...)
1369+ {
1370+ set_if_failed = true;
1371+ cerr << "Failed reading the configuration." << endl;
1372+ };
1373+ if (config.size() != 12)
1374+ {
1375+ set_if_failed = true;
1376+ cerr << "Did not find 12 parameters." << endl;
1377+ };
1378+ // iterator test
1379+ try
1380+ {
1381+ conf_reader::iterator c = config.begin();
1382+ conf_reader::iterator e = config.end();
1383+ while (c != e)
1384+ {
1385+ cout << "\t\"" << c->first << "\"=\"" << c->second
1386+ << "\"" << endl;
1387+ c++;
1388+ };
1389+ }
1390+ catch (...)
1391+ {
1392+ set_if_failed = true;
1393+ cerr << "Iterator test failed." << endl;
1394+ };
1395+ // template test.
1396+ int test = config.get<int>("test",-1);
1397+ int test2 = config.get<int>("test2",-1);
1398+ string test3 = config.get<string>("test3","not specified");
1399+ double test4 = config.get<double>("test",-1);
1400+ double test5 = config.get<double>("test2",-1);
1401+ cout << "(int) test = " << test
1402+ << "\n(int) test2 = " << test2
1403+ << "\n(string) test3 = \"" << test3 << "\""
1404+ << "\n(double) test = " << test4
1405+ << "\n(double) test2 = " << test5
1406+ << endl;
1407+ if (
1408+ (test != 1) or (test2 != 0)
1409+ or (test3 != "jack danials")
1410+ or (test4 != 1.0) or (test5 != 71.837486)
1411+ )
1412+ {
1413+ set_if_failed = true;
1414+ cerr << "** Template test failed." << endl;
1415+ };
1416+ // exists test.
1417+ cout << "?var \"--doit\" exists? "
1418+ << (config.exists("--doit") ? "Yes" : "No")
1419+ << endl;
1420+ if (!config.exists("--doit"))
1421+ {
1422+ set_if_failed = true;
1423+ cerr << "exists() test failed." << endl;
1424+ };
1425+ vector<int> intlist = config.getall<int>("test");
1426+ cout << "valid int \"test\" values:" << endl;
1427+ for (unsigned int i=0; i < intlist.size(); i++)
1428+ {
1429+ cout << "\t" << i << ": " << intlist[i] << endl;
1430+ };
1431+ if (intlist.size() != 2)
1432+ {
1433+ set_if_failed = true;
1434+ cerr << "getall<int>() did not find 2 parameters." << endl;
1435+ };
1436+ strlist strings = config.getall<string>("test");
1437+ cout << "valid string \"test\" values:" << endl;
1438+ for (unsigned int i=0; i < strings.size(); i++)
1439+ {
1440+ cout << "\t" << i << ": " << strings[i] << endl;
1441+ };
1442+ if (strings.size() != 3)
1443+ {
1444+ set_if_failed = true;
1445+ cerr << "getall<string>() did not find 3 parameters." << endl;
1446+ };
1447+ if (set_if_failed)
1448+ {
1449+ cerr << "** ntrb::conf_reader UNIT TEST FAILED. **" << endl;
1450+ log.fatal("UNIT TEST FAILED");
1451+ };
1452+ log.information("Run Complete");
1453+ return set_if_failed;
1454+};
1455
1456=== added file 'common/confreader/test.config'
1457--- common/confreader/test.config 1970-01-01 00:00:00 +0000
1458+++ common/confreader/test.config 2011-08-25 04:57:16 +0000
1459@@ -0,0 +1,27 @@
1460+###### config reader test file ######
1461+# use this command line to properly test this:
1462+#
1463+# ./conftest test=1 test2=2 test2=71.837486 test3="jack danials" --doit
1464+#
1465+# You should get a warning about problems reading dummyfile, and 12
1466+# variables listed. "test" should be 2 overridden by the command line.
1467+# You can test the ability to override the config file name with the
1468+# command:
1469+#
1470+# ./conftest configfile=dummy
1471+#
1472+# It should complain about problems reading dummy, and no variables
1473+# should be populated.
1474+#
1475+
1476+fileversion version 1.0
1477+hashtest \#surrounded\# \#by\# \#hashes\#
1478+test nonsense # should be overridden by commmand line
1479+test duh! # what happens here?
1480+\#starthash should start with hash (\#) symbol
1481+test 21 # should only be seen in getall<int>();
1482+test3 Working line.
1483+
1484+*INCLUDE dummyfile
1485+#*INCLUDE ../../salesman/tests/bc_bench.config
1486+lastline this should be complete
1487
1488=== added directory 'common/lib'
1489=== added directory 'common/logger'
1490=== added file 'common/logger/Makefile'
1491--- common/logger/Makefile 1970-01-01 00:00:00 +0000
1492+++ common/logger/Makefile 2011-08-25 04:57:16 +0000
1493@@ -0,0 +1,42 @@
1494+#***********************************************
1495+#This file is part of the NRTB project (https://launchpad.net/nrtb).
1496+#
1497+# NRTB is free software: you can redistribute it and/or modify
1498+# it under the terms of the GNU General Public License as published by
1499+# the Free Software Foundation, either version 3 of the License, or
1500+# (at your option) any later version.
1501+#
1502+# NRTB is distributed in the hope that it will be useful,
1503+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1504+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1505+# GNU General Public License for more details.
1506+#
1507+# You should have received a copy of the GNU General Public License
1508+# along with NRTB. If not, see <http://www.gnu.org/licenses/>.
1509+#
1510+#***********************************************
1511+
1512+lib: log_test
1513+ @echo "Testing..."
1514+ @rm -f test_output.log
1515+ @./log_test
1516+ @grep "Program run complete." test_output.log
1517+ @cp -fv log_setup.h ../include
1518+ @cp -fv log_setup.o ../obj
1519+
1520+
1521+log_setup.o: log_setup.h log_setup.cpp Makefile
1522+ @rm -f log_setup.o
1523+ g++ -c log_setup.cpp -I ../include
1524+
1525+log_test: log_setup.o log_test.cpp Makefile
1526+ @rm -vf log_test
1527+ g++ -c log_test.cpp -I../include
1528+ g++ -o log_test log_setup.o log_test.o -lPocoFoundation
1529+# g++ -g common_test.cpp -idirafter . -o common_test
1530+
1531+clean:
1532+ @rm -vf *.o log_test ../include/log_setup.h ../obj/log_setup.o test_output.log
1533+
1534+
1535+
1536
1537=== added file 'common/logger/log_setup.cpp'
1538--- common/logger/log_setup.cpp 1970-01-01 00:00:00 +0000
1539+++ common/logger/log_setup.cpp 2011-08-25 04:57:16 +0000
1540@@ -0,0 +1,43 @@
1541+/***********************************************
1542+ This file is part of the NRTB project (https://*launchpad.net/nrtb).
1543+
1544+ NRTB is free software: you can redistribute it and/or modify
1545+ it under the terms of the GNU General Public License as published by
1546+ the Free Software Foundation, either version 3 of the License, or
1547+ (at your option) any later version.
1548+
1549+ NRTB is distributed in the hope that it will be useful,
1550+ but WITHOUT ANY WARRANTY; without even the implied warranty of
1551+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1552+ GNU General Public License for more details.
1553+
1554+ You should have received a copy of the GNU General Public License
1555+ along with NRTB. If not, see <http://www.gnu.org/licenses/>.
1556+
1557+ **********************************************/
1558+
1559+#include "log_setup.h"
1560+
1561+#include "Poco/SimpleFileChannel.h"
1562+#include "Poco/FormattingChannel.h"
1563+#include "Poco/PatternFormatter.h"
1564+#include "Poco/Logger.h"
1565+#include "Poco/AutoPtr.h"
1566+
1567+using Poco::SimpleFileChannel;
1568+using Poco::FormattingChannel;
1569+using Poco::PatternFormatter;
1570+using Poco::Logger;
1571+using Poco::AutoPtr;
1572+
1573+void nrtb::setup_global_logging(const std::string & logfilename)
1574+{
1575+ AutoPtr<SimpleFileChannel> pFile(new SimpleFileChannel);
1576+ pFile->setProperty("path", logfilename);
1577+ pFile->setProperty("rotation", "250 K");
1578+ AutoPtr<PatternFormatter> pPF(new PatternFormatter);
1579+ pPF->setProperty("pattern", "%Y-%m-%d %H:%M:%S [%s:%p] %t");
1580+ AutoPtr<FormattingChannel> pFC(new FormattingChannel(pPF, pFile));
1581+ Logger::root().setChannel(pFC);
1582+ Logger::root().notice("Logging system initialized");
1583+}
1584\ No newline at end of file
1585
1586=== added file 'common/logger/log_setup.h'
1587--- common/logger/log_setup.h 1970-01-01 00:00:00 +0000
1588+++ common/logger/log_setup.h 2011-08-25 04:57:16 +0000
1589@@ -0,0 +1,30 @@
1590+/***********************************************
1591+ This file is part of the NRTB project (https://*launchpad.net/nrtb).
1592+
1593+ NRTB is free software: you can redistribute it and/or modify
1594+ it under the terms of the GNU General Public License as published by
1595+ the Free Software Foundation, either version 3 of the License, or
1596+ (at your option) any later version.
1597+
1598+ NRTB is distributed in the hope that it will be useful,
1599+ but WITHOUT ANY WARRANTY; without even the implied warranty of
1600+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1601+ GNU General Public License for more details.
1602+
1603+ You should have received a copy of the GNU General Public License
1604+ along with NRTB. If not, see <http://www.gnu.org/licenses/>.
1605+
1606+ **********************************************/
1607+
1608+#ifndef logger_setup_h
1609+#define logger_setup_h
1610+
1611+#include <string>
1612+
1613+namespace nrtb
1614+{
1615+
1616+ void setup_global_logging(const std::string & logfilename);
1617+}
1618+
1619+#endif //logger_setup_h
1620\ No newline at end of file
1621
1622=== added file 'common/logger/log_test.cpp'
1623--- common/logger/log_test.cpp 1970-01-01 00:00:00 +0000
1624+++ common/logger/log_test.cpp 2011-08-25 04:57:16 +0000
1625@@ -0,0 +1,46 @@
1626+/***********************************************
1627+ This file is part of the NRTB project (https://*launchpad.net/nrtb).
1628+
1629+ NRTB is free software: you can redistribute it and/or modify
1630+ it under the terms of the GNU General Public License as published by
1631+ the Free Software Foundation, either version 3 of the License, or
1632+ (at your option) any later version.
1633+
1634+ NRTB is distributed in the hope that it will be useful,
1635+ but WITHOUT ANY WARRANTY; without even the implied warranty of
1636+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1637+ GNU General Public License for more details.
1638+
1639+ You should have received a copy of the GNU General Public License
1640+ along with NRTB. If not, see <http://www.gnu.org/licenses/>.
1641+
1642+ **********************************************/
1643+
1644+#include "log_setup.h"
1645+
1646+#include <string>
1647+#include <iostream>
1648+#include <Poco/Logger.h>
1649+#include "Poco/LogStream.h"
1650+
1651+using namespace std;
1652+
1653+int main()
1654+{
1655+ bool set_if_failed = false;
1656+ try
1657+ {
1658+ nrtb::setup_global_logging("test_output.log");
1659+ Poco::Logger & logger = Poco::Logger::get("log_test");
1660+ logger.notice("Logging should be set up now.");
1661+ Poco::LogStream log(logger);
1662+ log << "This message used the stream interface" << endl;
1663+ logger.notice("Program run complete.");
1664+ }
1665+ catch (...)
1666+ {
1667+ set_if_failed = true;
1668+ cout << "** UNIT TEST FAILED **" << endl;
1669+ };
1670+ return set_if_failed;
1671+}
1672
1673=== removed directory 'common/plugin_loader'
1674=== removed file 'common/plugin_loader/Makefile'
1675--- common/plugin_loader/Makefile 2010-01-14 02:24:25 +0000
1676+++ common/plugin_loader/Makefile 1970-01-01 00:00:00 +0000
1677@@ -1,29 +0,0 @@
1678-
1679-build: plugin_wrapper.o plugin_manager.o
1680- @echo build complete
1681-
1682-plugin_wrapper.o: plugin_wrapper.h plugin_wrapper.cpp Makefile
1683- @rm -f plugin_wrapper.o
1684- g++ -c -O3 plugin_wrapper.cpp -idirafter ../../include3
1685-# g++ -c -g plugin_wrapper.cpp -idirafter ../../include3 -idirafter /usr/local/include/boost-1_31
1686-
1687-plugin_manager.o: plugin_manager.h plugin_manager.cpp Makefile
1688- @rm -f plugin_manager.o
1689- g++ -c -O3 plugin_manager.cpp -idirafter ../../include3
1690-# g++ -c -g plugin_wrapper.cpp -idirafter ../../include3 -idirafter /usr/local/include/boost-1_31
1691-
1692-test: plugin_wrapper.o plugin_manager.o wrapper_test.cpp
1693- @rm -f plugin_test
1694- g++ -c plugin_test.cpp -idirafter ../../include3 -idirafter /usr/local/include/boost-1_31
1695-# g++ -c -g conftest.cpp -idirafter ../../include3 -idirafter /usr/local/include/boost-1_31
1696- g++ -o plugtest plugtest.o plugin_wrapper.o plugin_manager.o -l ricklib3 -L../../lib/
1697-
1698-clean:
1699- @rm -rvf *.o plugin_test ../../include3/plugin_wrapper.h ../../include3/plugin_manager.h
1700- ar -d ../../lib/libricklib3.a plugin_wrapper.o plugin_manager.o
1701- @echo all objects and executables have been erased.
1702-
1703-lib: test
1704- @ar -r ../../lib/libricklib3.a plugin_wrapper.o plugin_manager.o
1705- @echo the plugin_wrapper class has been added to the library
1706- @cp -fv plugin_wrapper.h plugin_manager.h ../../include3
1707
1708=== removed directory 'common/plugin_loader/doc'
1709=== removed file 'common/plugin_loader/doc/plugins.xmi'
1710--- common/plugin_loader/doc/plugins.xmi 2010-01-14 02:24:25 +0000
1711+++ common/plugin_loader/doc/plugins.xmi 1970-01-01 00:00:00 +0000
1712@@ -1,339 +0,0 @@
1713-<?xml version="1.0" encoding="UTF-8"?>
1714-<XMI xmlns:UML="http://schema.omg.org/spec/UML/1.3" verified="false" timestamp="2008-07-12T19:11:33" xmi.version="1.2" >
1715- <XMI.header>
1716- <XMI.documentation>
1717- <XMI.exporter>umbrello uml modeller http://uml.sf.net</XMI.exporter>
1718- <XMI.exporterVersion>1.5.8</XMI.exporterVersion>
1719- <XMI.exporterEncoding>UnicodeUTF8</XMI.exporterEncoding>
1720- </XMI.documentation>
1721- <XMI.metamodel xmi.name="UML" href="UML.xml" xmi.version="1.3" />
1722- </XMI.header>
1723- <XMI.content>
1724- <UML:Model isSpecification="false" isLeaf="false" isRoot="false" xmi.id="m1" isAbstract="false" name="UML Model" >
1725- <UML:Namespace.ownedElement>
1726- <UML:Stereotype isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="folder" isRoot="false" isAbstract="false" name="folder" />
1727- <UML:Stereotype isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="datatype" isRoot="false" isAbstract="false" name="datatype" />
1728- <UML:Stereotype isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="singleton&lt;work_queue_thread&lt;message>>" isRoot="false" isAbstract="false" name="singleton&lt;work_queue_thread&lt;message>>" />
1729- <UML:Stereotype isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="singleton" isRoot="false" isAbstract="false" name="singleton" />
1730- <UML:Stereotype isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="thread::run" isRoot="false" isAbstract="false" name="thread::run" />
1731- <UML:Stereotype isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="simObject, ricklib::thread" isRoot="false" isAbstract="false" name="simObject, ricklib::thread" />
1732- <UML:Stereotype isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="map&lt;string,plugin_list>" isRoot="false" isAbstract="false" name="map&lt;string,plugin_list>" />
1733- <UML:Stereotype isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="map&lt;string,plugins_by_name>" isRoot="false" isAbstract="false" name="map&lt;string,plugins_by_name>" />
1734- <UML:Stereotype isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="triad&lt;double>" isRoot="false" isAbstract="false" name="triad&lt;double>" />
1735- <UML:Model stereotype="folder" isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="Logical View" isRoot="false" isAbstract="false" name="Logical View" >
1736- <UML:Namespace.ownedElement>
1737- <UML:Package stereotype="folder" isSpecification="false" isLeaf="false" visibility="public" namespace="Logical View" xmi.id="Datatypes" isRoot="false" isAbstract="false" name="Datatypes" >
1738- <UML:Namespace.ownedElement>
1739- <UML:DataType stereotype="datatype" isSpecification="false" isLeaf="false" visibility="public" namespace="Datatypes" xmi.id="Ffh4kk3Ca5c0" isRoot="false" isAbstract="false" name="int" />
1740- <UML:DataType stereotype="datatype" isSpecification="false" isLeaf="false" visibility="public" namespace="Datatypes" xmi.id="dwxIyKY9DGUT" isRoot="false" isAbstract="false" name="char" />
1741- <UML:DataType stereotype="datatype" isSpecification="false" isLeaf="false" visibility="public" namespace="Datatypes" xmi.id="80aYqgH4Lz85" isRoot="false" isAbstract="false" name="bool" />
1742- <UML:DataType stereotype="datatype" isSpecification="false" isLeaf="false" visibility="public" namespace="Datatypes" xmi.id="hBHFFrFqnD9j" isRoot="false" isAbstract="false" name="float" />
1743- <UML:DataType stereotype="datatype" isSpecification="false" isLeaf="false" visibility="public" namespace="Datatypes" xmi.id="VfqivJ93JiZ9" isRoot="false" isAbstract="false" name="double" />
1744- <UML:DataType stereotype="datatype" isSpecification="false" isLeaf="false" visibility="public" namespace="Datatypes" xmi.id="OrDjoJmVT3kg" isRoot="false" isAbstract="false" name="short" />
1745- <UML:DataType stereotype="datatype" isSpecification="false" isLeaf="false" visibility="public" namespace="Datatypes" xmi.id="syWd9dNeIDLC" isRoot="false" isAbstract="false" name="long" />
1746- <UML:DataType stereotype="datatype" isSpecification="false" isLeaf="false" visibility="public" namespace="Datatypes" xmi.id="WSFnAnxYc8FQ" isRoot="false" isAbstract="false" name="unsigned int" />
1747- <UML:DataType stereotype="datatype" isSpecification="false" isLeaf="false" visibility="public" namespace="Datatypes" xmi.id="Q1tt2bZuZ5Yg" isRoot="false" isAbstract="false" name="unsigned short" />
1748- <UML:DataType stereotype="datatype" isSpecification="false" isLeaf="false" visibility="public" namespace="Datatypes" xmi.id="htJz4eBZ4PMF" isRoot="false" isAbstract="false" name="unsigned long" />
1749- <UML:DataType stereotype="datatype" isSpecification="false" isLeaf="false" visibility="public" namespace="Datatypes" xmi.id="CHlmQ1Co03h3" isRoot="false" isAbstract="false" name="string" />
1750- <UML:DataType stereotype="datatype" isSpecification="false" isLeaf="false" visibility="public" namespace="Datatypes" xmi.id="z2PlKwwnqyeq" isRoot="false" isAbstract="false" name="void *" />
1751- <UML:DataType stereotype="datatype" isSpecification="false" isLeaf="false" visibility="public" namespace="Datatypes" xmi.id="FWxLRQq7CGim" isRoot="false" isAbstract="false" name="abstract_weapon *" />
1752- <UML:DataType stereotype="datatype" isSpecification="false" isLeaf="false" visibility="public" namespace="Datatypes" xmi.id="81JjStCiP83q" isRoot="false" isAbstract="false" name="abstract_sensor *" />
1753- <UML:DataType stereotype="datatype" isSpecification="false" isLeaf="false" visibility="public" namespace="Datatypes" xmi.id="qUlL5Ja8j1rY" isRoot="false" isAbstract="false" name="abstract_chassis *" />
1754- </UML:Namespace.ownedElement>
1755- </UML:Package>
1756- <UML:Class isSpecification="false" isLeaf="false" visibility="public" namespace="Logical View" xmi.id="225YrWUg6CUk" isRoot="false" isAbstract="true" name="plugin_wrapper" >
1757- <UML:GeneralizableElement.generalization>
1758- <UML:Generalization xmi.idref="vIs8sXpoyxA8" />
1759- </UML:GeneralizableElement.generalization>
1760- <UML:Classifier.feature>
1761- <UML:Attribute comment="The type of plugin represented here (i.e. weapon, sensor, etc.), must match the types defined for sim engine use." isSpecification="false" visibility="protected" xmi.id="0kYAfH74JA7p" type="CHlmQ1Co03h3" name="plugin_type" />
1762- <UML:Attribute comment="The version number of this plugin." isSpecification="false" visibility="protected" xmi.id="ToJfQEMPzsZc" type="hBHFFrFqnD9j" name="version" />
1763- <UML:Attribute comment="The name of this plugin." isSpecification="false" visibility="protected" xmi.id="9egRonGpPYT7" type="CHlmQ1Co03h3" name="plugin_name" />
1764- <UML:Attribute comment="The path of the shared library implementing this plugin." isSpecification="false" visibility="protected" xmi.id="ZRl1ZW499wAW" type="YMxgqxXjjUHD" name="path" />
1765- <UML:Attribute isSpecification="false" visibility="protected" xmi.id="wOLstKsOU3xd" type="ZSpIFcMrTgYw" name="factory_address" />
1766- <UML:Operation comment="Called to load the library." isSpecification="false" isLeaf="false" visibility="public" xmi.id="evlKlgpUQJmb" isRoot="false" isAbstract="false" isQuery="false" name="load" >
1767- <UML:BehavioralFeature.parameter>
1768- <UML:Parameter comment="The path of shared library file implementing the plugin." isSpecification="false" visibility="private" xmi.id="95QVtX2h9xRU" value="" type="YMxgqxXjjUHD" name="path" />
1769- </UML:BehavioralFeature.parameter>
1770- </UML:Operation>
1771- <UML:Operation comment="Called to get the raw address to the factory... you'll need to cast it to the correct type." isSpecification="false" isLeaf="false" visibility="public" xmi.id="j7HBVbv71scs" isRoot="false" isAbstract="false" isQuery="false" name="plugin_wrapper" >
1772- <UML:BehavioralFeature.parameter>
1773- <UML:Parameter comment="The path to the library to be loaded." isSpecification="false" visibility="private" xmi.id="SOCOuP71SVVL" value="" type="YMxgqxXjjUHD" name="loadpath" />
1774- </UML:BehavioralFeature.parameter>
1775- </UML:Operation>
1776- <UML:Operation comment="Returns the plugin_type for the contained plugin." isSpecification="false" isLeaf="false" visibility="public" xmi.id="gx1dfJPPtVf7" isRoot="false" isAbstract="false" isQuery="false" name="getType" >
1777- <UML:BehavioralFeature.parameter>
1778- <UML:Parameter kind="return" xmi.id="hG7NjAual1aw" type="CHlmQ1Co03h3" />
1779- </UML:BehavioralFeature.parameter>
1780- </UML:Operation>
1781- <UML:Operation comment="Returns the version information for the contained plugin." isSpecification="false" isLeaf="false" visibility="public" xmi.id="lh0Se8lUfT5X" isRoot="false" isAbstract="false" isQuery="false" name="getVersion" >
1782- <UML:BehavioralFeature.parameter>
1783- <UML:Parameter kind="return" xmi.id="jxjLJCew2LSN" type="hBHFFrFqnD9j" />
1784- </UML:BehavioralFeature.parameter>
1785- </UML:Operation>
1786- <UML:Operation comment="Returns the name of the plugin associated with this wrapper." isSpecification="false" isLeaf="false" visibility="public" xmi.id="fqiWLNb62bXe" isRoot="false" isAbstract="false" isQuery="false" name="getName" >
1787- <UML:BehavioralFeature.parameter>
1788- <UML:Parameter kind="return" xmi.id="g1RhawLICSft" type="CHlmQ1Co03h3" />
1789- </UML:BehavioralFeature.parameter>
1790- </UML:Operation>
1791- <UML:Operation comment="Returns the full file path for the plugin loaded." isSpecification="false" isLeaf="false" visibility="public" xmi.id="EADACWaXDZwu" isRoot="false" isAbstract="false" isQuery="false" name="getPath" >
1792- <UML:BehavioralFeature.parameter>
1793- <UML:Parameter kind="return" xmi.id="9tDR3e4vEZMa" type="YMxgqxXjjUHD" />
1794- </UML:BehavioralFeature.parameter>
1795- </UML:Operation>
1796- <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="n1z8iZxdRl3R" isRoot="false" isAbstract="false" isQuery="false" name="newInstance" />
1797- </UML:Classifier.feature>
1798- </UML:Class>
1799- <UML:Package isSpecification="false" isLeaf="false" visibility="public" namespace="Logical View" xmi.id="1dJfkTAS2RQE" isRoot="false" isAbstract="false" name="std" >
1800- <UML:Namespace.ownedElement/>
1801- </UML:Package>
1802- <UML:Package isSpecification="false" isLeaf="false" visibility="public" namespace="Logical View" xmi.id="rsozaUfviJVQ" isRoot="false" isAbstract="false" name="boost" >
1803- <UML:Namespace.ownedElement>
1804- <UML:Package isSpecification="false" isLeaf="false" visibility="public" namespace="rsozaUfviJVQ" xmi.id="hQQSxzuiyRF1" isRoot="false" isAbstract="false" name="filesystem" >
1805- <UML:Namespace.ownedElement>
1806- <UML:Class isSpecification="false" isLeaf="false" visibility="public" namespace="hQQSxzuiyRF1" xmi.id="YMxgqxXjjUHD" isRoot="false" isAbstract="false" name="path" />
1807- </UML:Namespace.ownedElement>
1808- </UML:Package>
1809- </UML:Namespace.ownedElement>
1810- </UML:Package>
1811- <UML:Class isSpecification="false" isLeaf="false" visibility="public" namespace="Logical View" xmi.id="ZSpIFcMrTgYw" isRoot="false" isAbstract="false" name="factory_ptr" />
1812- <UML:Class isSpecification="false" isLeaf="false" visibility="public" namespace="Logical View" xmi.id="5RxrSpb7LxuI" isRoot="false" isAbstract="false" name="weapon_plugin" >
1813- <UML:GeneralizableElement.generalization>
1814- <UML:Generalization xmi.idref="FgcyZa21VrTL" />
1815- </UML:GeneralizableElement.generalization>
1816- <UML:Classifier.feature>
1817- <UML:Operation comment="Allocates and constructs the abstract_weapon descendent and returns a smart pointer to the new object." isSpecification="false" isLeaf="false" visibility="public" xmi.id="WStI1XSjbrPt" isRoot="false" isAbstract="false" isQuery="false" name="newWeapon" />
1818- </UML:Classifier.feature>
1819- </UML:Class>
1820- <UML:Generalization isSpecification="false" child="5RxrSpb7LxuI" visibility="public" namespace="Logical View" xmi.id="FgcyZa21VrTL" parent="225YrWUg6CUk" discriminator="" name="" />
1821- <UML:Class isSpecification="false" isLeaf="false" visibility="public" namespace="Logical View" xmi.id="Y1oRrxMFYzBw" isRoot="false" isAbstract="false" name="sensor_plugin" >
1822- <UML:GeneralizableElement.generalization>
1823- <UML:Generalization xmi.idref="QAC4gEA4Cbfh" />
1824- </UML:GeneralizableElement.generalization>
1825- <UML:Classifier.feature>
1826- <UML:Operation comment="Allocates and constructs a descendent of abstract_sensor and returns a smart pointer to the new object." isSpecification="false" isLeaf="false" visibility="public" xmi.id="0zNHSOUVzjY3" isRoot="false" isAbstract="false" isQuery="false" name="newSensor" />
1827- </UML:Classifier.feature>
1828- </UML:Class>
1829- <UML:Class isSpecification="false" isLeaf="false" visibility="public" namespace="Logical View" xmi.id="PyRdWPmTPloe" isRoot="false" isAbstract="false" name="etc_plugin" >
1830- <UML:GeneralizableElement.generalization>
1831- <UML:Generalization xmi.idref="nenipvZyQWG1" />
1832- </UML:GeneralizableElement.generalization>
1833- <UML:Classifier.feature>
1834- <UML:Operation comment="Returns a smart to a new object of the appropriate class." isSpecification="false" isLeaf="false" visibility="public" xmi.id="EC8j9pFAdKdx" isRoot="false" isAbstract="false" isQuery="false" name="newEtc" />
1835- </UML:Classifier.feature>
1836- </UML:Class>
1837- <UML:Generalization isSpecification="false" child="Y1oRrxMFYzBw" visibility="public" namespace="Logical View" xmi.id="QAC4gEA4Cbfh" parent="225YrWUg6CUk" discriminator="" name="" />
1838- <UML:Generalization isSpecification="false" child="225YrWUg6CUk" visibility="public" namespace="Logical View" xmi.id="vIs8sXpoyxA8" parent="PyRdWPmTPloe" discriminator="" name="" />
1839- <UML:Generalization isSpecification="false" child="PyRdWPmTPloe" visibility="public" namespace="Logical View" xmi.id="nenipvZyQWG1" parent="225YrWUg6CUk" discriminator="" name="" />
1840- <UML:Class stereotype="singleton" isSpecification="false" isLeaf="false" visibility="public" namespace="Logical View" xmi.id="WT0Ka8jF10jk" isRoot="false" isAbstract="false" name="plugin_manager" >
1841- <UML:Classifier.feature>
1842- <UML:Attribute isSpecification="false" visibility="protected" xmi.id="HPMtw9k0PQzT" type="ohv3mPtcgGzX" name="plugins" />
1843- <UML:Operation comment="Loads all plugins found in the default paths (defined by the configuration manager singleton not shown here)." isSpecification="false" isLeaf="false" visibility="public" xmi.id="46RtlzCdqiGw" isRoot="false" isAbstract="false" isQuery="false" name="load_all" />
1844- <UML:Operation comment="Returns a reference to the requested plugin_wrapper or throws if it is not found." isSpecification="false" isLeaf="false" visibility="public" xmi.id="YVcYycxZS0QM" isRoot="false" isAbstract="false" isQuery="false" name="create_instance" >
1845- <UML:BehavioralFeature.parameter>
1846- <UML:Parameter comment="The class of plugin requested" isSpecification="false" visibility="private" xmi.id="r12fGT7KZYDL" value="" type="CHlmQ1Co03h3" name="plugin_type" />
1847- <UML:Parameter comment="The name of the plugin requested." isSpecification="false" visibility="private" xmi.id="WNwM6CGchsAd" value="" type="CHlmQ1Co03h3" name="name" />
1848- </UML:BehavioralFeature.parameter>
1849- </UML:Operation>
1850- <UML:Operation comment="Releases all plugins held by the manager." isSpecification="false" isLeaf="false" visibility="public" xmi.id="niINN8W0bcBT" isRoot="false" isAbstract="false" isQuery="false" name="release_all" />
1851- <UML:Operation comment="For debugging, returns a formatted string with a list of all plugins loaded including types, names and version number." isSpecification="false" isLeaf="false" visibility="public" xmi.id="HQVTuW3lNEMc" isRoot="false" isAbstract="false" isQuery="false" name="dump" >
1852- <UML:BehavioralFeature.parameter>
1853- <UML:Parameter kind="return" xmi.id="6dRTso5oWpKV" type="CHlmQ1Co03h3" />
1854- </UML:BehavioralFeature.parameter>
1855- </UML:Operation>
1856- <UML:Operation comment="Loads one plugin. Will throw if the provided path is invalid or does not contain a valid plugin." isSpecification="false" isLeaf="false" visibility="public" xmi.id="yilX1rI1K1Ye" isRoot="false" isAbstract="false" isQuery="false" name="load_one" >
1857- <UML:BehavioralFeature.parameter>
1858- <UML:Parameter comment="Path to the shared libary to be loaded." isSpecification="false" visibility="private" xmi.id="RbQYsO69oaag" value="" type="YMxgqxXjjUHD" name="path" />
1859- </UML:BehavioralFeature.parameter>
1860- </UML:Operation>
1861- <UML:Operation comment="Releases one plugin, specified by type and name. WIll throw if the plugin is not found." isSpecification="false" isLeaf="false" visibility="public" xmi.id="SOhcCFAtLoIm" isRoot="false" isAbstract="false" isQuery="false" name="release_one" >
1862- <UML:BehavioralFeature.parameter>
1863- <UML:Parameter comment="The type of the single plugin to be released." isSpecification="false" visibility="private" xmi.id="e6qSbfm4JPXG" value="" type="CHlmQ1Co03h3" name="plugin_type" />
1864- <UML:Parameter comment="The name of the single plugin to be released." isSpecification="false" visibility="private" xmi.id="1Zq4BqfcCMEM" value="" type="CHlmQ1Co03h3" name="plugin_name" />
1865- </UML:BehavioralFeature.parameter>
1866- </UML:Operation>
1867- <UML:Operation comment="Returns a ricklib::str_list contining all the class names currently loaded." isSpecification="false" isLeaf="false" visibility="public" xmi.id="cu3qBV5M3heD" isRoot="false" isAbstract="false" isQuery="false" name="get_class_names" />
1868- <UML:Operation comment="returns a ricklib::str_list containing all the plugin names which match a given class." isSpecification="false" isLeaf="false" visibility="public" xmi.id="D9eyZpw9jz0s" isRoot="false" isAbstract="false" isQuery="false" name="get_class_plugin_names" >
1869- <UML:BehavioralFeature.parameter>
1870- <UML:Parameter comment="The name of the plugin class to be returned." isSpecification="false" visibility="private" xmi.id="KaC8tCfxNnbM" value="" type="CHlmQ1Co03h3" name="class_name" />
1871- </UML:BehavioralFeature.parameter>
1872- </UML:Operation>
1873- </UML:Classifier.feature>
1874- <UML:Namespace.ownedElement>
1875- <UML:Class stereotype="map&lt;string,plugins_by_name>" isSpecification="false" isLeaf="false" visibility="public" namespace="WT0Ka8jF10jk" xmi.id="qoJ98w4raNBZ" isRoot="false" isAbstract="false" name="plugin_lists_by_class" />
1876- </UML:Namespace.ownedElement>
1877- </UML:Class>
1878- <UML:Class stereotype="map&lt;string,plugin_list>" isSpecification="false" isLeaf="false" visibility="public" namespace="Logical View" xmi.id="eLKy62PhoKwL" isRoot="false" isAbstract="false" name="plugins_by_name" />
1879- <UML:Association isSpecification="false" visibility="public" namespace="Logical View" xmi.id="TBw9yE3Jk8tz" name="" >
1880- <UML:Association.connection>
1881- <UML:AssociationEnd isSpecification="false" visibility="public" changeability="changeable" isNavigable="true" xmi.id="OBQB4JJHyejP" aggregation="aggregate" type="qoJ98w4raNBZ" name="" multiplicity="0..n" />
1882- <UML:AssociationEnd isSpecification="false" visibility="public" changeability="changeable" isNavigable="true" xmi.id="tUGb3kMc58zH" aggregation="none" type="eLKy62PhoKwL" name="" />
1883- </UML:Association.connection>
1884- </UML:Association>
1885- <UML:Association isSpecification="false" visibility="public" namespace="Logical View" xmi.id="xRtgdkgsvOEx" name="" >
1886- <UML:Association.connection>
1887- <UML:AssociationEnd isSpecification="false" visibility="public" changeability="changeable" isNavigable="true" xmi.id="Vq2iVy3r9S2B" aggregation="aggregate" type="225YrWUg6CUk" name="" multiplicity="1..n" />
1888- <UML:AssociationEnd isSpecification="false" visibility="public" changeability="changeable" isNavigable="true" xmi.id="lJSix95qbJQe" aggregation="none" type="eLKy62PhoKwL" name="" />
1889- </UML:Association.connection>
1890- </UML:Association>
1891- <UML:Association isSpecification="false" visibility="public" namespace="Logical View" xmi.id="iYP4MN0Qbl9T" name="" >
1892- <UML:Association.connection>
1893- <UML:AssociationEnd isSpecification="false" visibility="public" changeability="changeable" isNavigable="true" xmi.id="4mG9sDPO2P4V" aggregation="aggregate" type="eLKy62PhoKwL" name="" multiplicity="1..n" />
1894- <UML:AssociationEnd isSpecification="false" visibility="public" changeability="changeable" isNavigable="true" xmi.id="N7KVZMgJd7zb" aggregation="none" type="225YrWUg6CUk" name="" />
1895- </UML:Association.connection>
1896- </UML:Association>
1897- <UML:Class isSpecification="false" isLeaf="false" visibility="public" namespace="Logical View" xmi.id="ohv3mPtcgGzX" isRoot="false" isAbstract="false" name="plugin_lists_by_class" />
1898- <UML:Association isSpecification="false" visibility="public" namespace="Logical View" xmi.id="D6HDTiBxzfAu" name="" >
1899- <UML:Association.connection>
1900- <UML:AssociationEnd isSpecification="false" visibility="public" changeability="changeable" isNavigable="true" xmi.id="uwmwLqPgvj9T" aggregation="composite" type="WT0Ka8jF10jk" name="" />
1901- <UML:AssociationEnd isSpecification="false" visibility="public" changeability="changeable" isNavigable="true" xmi.id="5qkhvjG9ldx6" aggregation="none" type="WT0Ka8jF10jk" name="" />
1902- </UML:Association.connection>
1903- </UML:Association>
1904- <UML:Association isSpecification="false" visibility="public" namespace="Logical View" xmi.id="ozgldpf0rhYJ" name="" >
1905- <UML:Association.connection>
1906- <UML:AssociationEnd isSpecification="false" visibility="public" changeability="changeable" isNavigable="true" xmi.id="RSWw91M3x6yG" aggregation="composite" type="WT0Ka8jF10jk" name="" />
1907- <UML:AssociationEnd isSpecification="false" visibility="public" changeability="changeable" isNavigable="true" xmi.id="wNuq74JAs3rn" aggregation="none" type="qoJ98w4raNBZ" name="" />
1908- </UML:Association.connection>
1909- </UML:Association>
1910- </UML:Namespace.ownedElement>
1911- <XMI.extension xmi.extender="umbrello" >
1912- <diagrams>
1913- <diagram snapgrid="0" showattsig="1" fillcolor="#ffffc0" linewidth="0" zoom="100" showgrid="0" showopsig="1" usefillcolor="1" snapx="10" canvaswidth="808" snapy="10" showatts="1" xmi.id="DukLGrX7Qs7l" documentation="" type="1" showops="1" showpackage="0" name="Plugin Manager Overview" localid="" showstereotype="0" showscope="1" snapcsgrid="0" font="Sans,10,-1,5,50,0,0,0,0,0" linecolor="#ff0000" canvasheight="588" >
1914- <widgets>
1915- <classwidget usesdiagramfillcolor="0" width="352" showattsigs="601" x="445" fillcolor="#ffffc0" y="19" drawascircle="0" showopsigs="601" linewidth="none" height="234" usefillcolor="1" showpubliconly="0" showattributes="1" isinstance="0" xmi.id="225YrWUg6CUk" showoperations="1" showpackage="0" showscope="1" usesdiagramusefillcolor="0" font="Sans,10,-1,5,50,0,0,0,0,0" linecolor="#ff0000" />
1916- <classwidget usesdiagramfillcolor="0" width="378" showattsigs="601" x="6" fillcolor="#ffffc0" y="219" showopsigs="601" linewidth="none" height="198" usefillcolor="1" showpubliconly="0" showattributes="1" isinstance="0" xmi.id="WT0Ka8jF10jk" showoperations="1" showpackage="0" showscope="1" showstereotype="1" usesdiagramusefillcolor="0" font="Sans,10,-1,5,50,0,0,0,0,0" linecolor="#ff0000" />
1917- <classwidget usesdiagramfillcolor="0" width="200" showattsigs="600" x="48" fillcolor="#ffffc0" y="14" showopsigs="600" linewidth="none" height="54" usefillcolor="1" showpubliconly="0" showattributes="0" isinstance="0" xmi.id="eLKy62PhoKwL" showoperations="0" showpackage="0" showscope="1" showstereotype="1" usesdiagramusefillcolor="0" font="Sans,10,-1,5,50,0,0,0,0,0" linecolor="#ff0000" />
1918- <classwidget usesdiagramfillcolor="0" width="249" showattsigs="601" x="25" fillcolor="#ffffc0" y="114" showopsigs="601" linewidth="none" height="54" usefillcolor="1" showpubliconly="0" showattributes="1" isinstance="0" xmi.id="qoJ98w4raNBZ" showoperations="1" showpackage="0" showscope="1" showstereotype="1" usesdiagramusefillcolor="0" font="Sans,10,-1,5,50,0,0,0,0,0" linecolor="#ff0000" />
1919- <notewidget usesdiagramfillcolor="1" width="383" x="417" fillcolor="none" y="273" linewidth="none" height="251" usefillcolor="1" isinstance="0" xmi.id="cwXZkbyWc9J4" text="IMPORTANT NOTE:
1920-
1921-For this to work, plugin_wrapper must assume each plugin will export the following symbols:
1922-
1923-Variables:
1924- string PTYPE: the plugin type (weapon, sensor, etc.)
1925- string PNAME: the name of this particular plugin
1926- string PVER: the version number of this particular plugin
1927-
1928-Function
1929- abstract_? * PFACT(...) : the factory which creates the plugin (a c++ class instance). The precise signature of the fuction will vary between plugin types and is not the concern of the plugin manager, as it will not be called in that context. " usesdiagramusefillcolor="1" font="Sans,8,-1,5,50,0,0,0,0,0" linecolor="none" />
1930- </widgets>
1931- <messages/>
1932- <associations>
1933- <assocwidget totalcounta="2" indexa="1" totalcountb="2" indexb="1" linewidth="none" widgetbid="eLKy62PhoKwL" widgetaid="qoJ98w4raNBZ" xmi.id="TBw9yE3Jk8tz" type="501" linecolor="none" >
1934- <linepath>
1935- <startpoint startx="149" starty="114" />
1936- <endpoint endx="148" endy="68" />
1937- </linepath>
1938- <floatingtext usesdiagramfillcolor="1" width="32" x="151" fillcolor="none" y="90" linewidth="none" posttext="" role="701" height="22" usefillcolor="1" pretext="" isinstance="0" xmi.id="k5uTjsZAI36P" text="0..n" usesdiagramusefillcolor="1" font="Sans,10,-1,5,50,0,0,0,0,0" linecolor="none" />
1939- </assocwidget>
1940- <assocwidget totalcounta="2" indexa="1" totalcountb="2" indexb="1" linewidth="none" widgetbid="225YrWUg6CUk" widgetaid="eLKy62PhoKwL" xmi.id="iYP4MN0Qbl9T" type="501" linecolor="none" >
1941- <linepath>
1942- <startpoint startx="248" starty="41" />
1943- <endpoint endx="445" endy="136" />
1944- </linepath>
1945- <floatingtext usesdiagramfillcolor="1" width="32" x="246" fillcolor="none" y="24" linewidth="none" posttext="" role="701" height="22" usefillcolor="1" pretext="" isinstance="0" xmi.id="4RQzXODSk8Ir" text="1..n" usesdiagramusefillcolor="1" font="Sans,10,-1,5,50,0,0,0,0,0" linecolor="none" />
1946- </assocwidget>
1947- <assocwidget totalcounta="2" indexa="1" totalcountb="2" indexb="1" linewidth="none" widgetbid="qoJ98w4raNBZ" widgetaid="WT0Ka8jF10jk" xmi.id="ozgldpf0rhYJ" type="510" linecolor="none" >
1948- <linepath>
1949- <startpoint startx="195" starty="219" />
1950- <endpoint endx="149" endy="168" />
1951- </linepath>
1952- </assocwidget>
1953- </associations>
1954- </diagram>
1955- </diagrams>
1956- </XMI.extension>
1957- </UML:Model>
1958- <UML:Model stereotype="folder" isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="Use Case View" isRoot="false" isAbstract="false" name="Use Case View" >
1959- <UML:Namespace.ownedElement/>
1960- </UML:Model>
1961- <UML:Model stereotype="folder" isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="Component View" isRoot="false" isAbstract="false" name="Component View" >
1962- <UML:Namespace.ownedElement/>
1963- </UML:Model>
1964- <UML:Model stereotype="folder" isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="Deployment View" isRoot="false" isAbstract="false" name="Deployment View" >
1965- <UML:Namespace.ownedElement/>
1966- </UML:Model>
1967- <UML:Model stereotype="folder" isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="Entity Relationship Model" isRoot="false" isAbstract="false" name="Entity Relationship Model" >
1968- <UML:Namespace.ownedElement/>
1969- </UML:Model>
1970- </UML:Namespace.ownedElement>
1971- </UML:Model>
1972- </XMI.content>
1973- <XMI.extensions xmi.extender="umbrello" >
1974- <docsettings viewid="DukLGrX7Qs7l" documentation="" uniqueid="KaC8tCfxNnbM" />
1975- <listview>
1976- <listitem open="1" type="800" label="Views" >
1977- <listitem open="1" type="801" id="Logical View" >
1978- <listitem open="0" type="807" id="DukLGrX7Qs7l" label="Plugin Manager Overview" />
1979- <listitem open="1" type="813" id="PyRdWPmTPloe" >
1980- <listitem open="0" type="815" id="EC8j9pFAdKdx" />
1981- </listitem>
1982- <listitem open="1" type="813" id="ZSpIFcMrTgYw" />
1983- <listitem open="1" type="813" id="ohv3mPtcgGzX" />
1984- <listitem open="1" type="813" id="WT0Ka8jF10jk" >
1985- <listitem open="0" type="813" id="qoJ98w4raNBZ" />
1986- <listitem open="0" type="814" id="HPMtw9k0PQzT" />
1987- <listitem open="0" type="815" id="46RtlzCdqiGw" />
1988- <listitem open="0" type="815" id="YVcYycxZS0QM" />
1989- <listitem open="0" type="815" id="niINN8W0bcBT" />
1990- <listitem open="0" type="815" id="HQVTuW3lNEMc" />
1991- <listitem open="0" type="815" id="yilX1rI1K1Ye" />
1992- <listitem open="0" type="815" id="SOhcCFAtLoIm" />
1993- <listitem open="0" type="815" id="cu3qBV5M3heD" />
1994- <listitem open="0" type="815" id="D9eyZpw9jz0s" />
1995- </listitem>
1996- <listitem open="1" type="813" id="225YrWUg6CUk" >
1997- <listitem open="0" type="814" id="0kYAfH74JA7p" />
1998- <listitem open="0" type="814" id="ToJfQEMPzsZc" />
1999- <listitem open="0" type="814" id="9egRonGpPYT7" />
2000- <listitem open="0" type="814" id="ZRl1ZW499wAW" />
2001- <listitem open="0" type="814" id="wOLstKsOU3xd" />
2002- <listitem open="0" type="815" id="evlKlgpUQJmb" />
2003- <listitem open="0" type="815" id="j7HBVbv71scs" />
2004- <listitem open="0" type="815" id="gx1dfJPPtVf7" />
2005- <listitem open="0" type="815" id="lh0Se8lUfT5X" />
2006- <listitem open="0" type="815" id="fqiWLNb62bXe" />
2007- <listitem open="0" type="815" id="EADACWaXDZwu" />
2008- <listitem open="0" type="815" id="n1z8iZxdRl3R" />
2009- </listitem>
2010- <listitem open="1" type="813" id="eLKy62PhoKwL" />
2011- <listitem open="1" type="813" id="Y1oRrxMFYzBw" >
2012- <listitem open="0" type="815" id="0zNHSOUVzjY3" />
2013- </listitem>
2014- <listitem open="1" type="813" id="5RxrSpb7LxuI" >
2015- <listitem open="0" type="815" id="WStI1XSjbrPt" />
2016- </listitem>
2017- <listitem open="1" type="818" id="rsozaUfviJVQ" >
2018- <listitem open="1" type="818" id="hQQSxzuiyRF1" >
2019- <listitem open="1" type="813" id="YMxgqxXjjUHD" />
2020- </listitem>
2021- </listitem>
2022- <listitem open="1" type="818" id="1dJfkTAS2RQE" />
2023- <listitem open="1" type="830" id="Datatypes" >
2024- <listitem open="1" type="829" id="qUlL5Ja8j1rY" />
2025- <listitem open="1" type="829" id="81JjStCiP83q" />
2026- <listitem open="1" type="829" id="FWxLRQq7CGim" />
2027- <listitem open="1" type="829" id="80aYqgH4Lz85" />
2028- <listitem open="1" type="829" id="dwxIyKY9DGUT" />
2029- <listitem open="1" type="829" id="VfqivJ93JiZ9" />
2030- <listitem open="1" type="829" id="hBHFFrFqnD9j" />
2031- <listitem open="1" type="829" id="Ffh4kk3Ca5c0" />
2032- <listitem open="1" type="829" id="syWd9dNeIDLC" />
2033- <listitem open="1" type="829" id="OrDjoJmVT3kg" />
2034- <listitem open="1" type="829" id="CHlmQ1Co03h3" />
2035- <listitem open="1" type="829" id="WSFnAnxYc8FQ" />
2036- <listitem open="1" type="829" id="htJz4eBZ4PMF" />
2037- <listitem open="1" type="829" id="Q1tt2bZuZ5Yg" />
2038- <listitem open="1" type="829" id="z2PlKwwnqyeq" />
2039- </listitem>
2040- </listitem>
2041- <listitem open="1" type="802" id="Use Case View" />
2042- <listitem open="1" type="821" id="Component View" />
2043- <listitem open="1" type="827" id="Deployment View" />
2044- <listitem open="1" type="836" id="Entity Relationship Model" />
2045- </listitem>
2046- </listview>
2047- <codegeneration>
2048- <codegenerator language="C++" />
2049- </codegeneration>
2050- </XMI.extensions>
2051-</XMI>
2052
2053=== removed file 'common/plugin_loader/plugin_manager.cpp'
2054--- common/plugin_loader/plugin_manager.cpp 2010-01-14 02:24:25 +0000
2055+++ common/plugin_loader/plugin_manager.cpp 1970-01-01 00:00:00 +0000
2056@@ -1,127 +0,0 @@
2057-//
2058-// C++ Implementation: plugin_manager
2059-//
2060-// Description:
2061-//
2062-//
2063-// Author: Rick Stovall <rstovall@gabbie>, (C) 2008
2064-//
2065-// Copyright: See COPYING file that comes with this distribution
2066-//
2067-//
2068-
2069-#include "plugin_manager.h"
2070-
2071-//use boost::filesystem;
2072-//use boost::filesystem::directory_iterator;
2073-
2074-
2075-// TODO: review to make sure all methods from the .h are implemented.
2076-namespace NRTB
2077-{
2078-
2079- plugin_manager::plugin_manager()
2080- {
2081- // nop in this version.
2082- };
2083-
2084- plugin_manager::plugin_manager(const boost::filesystem::path loadpath)
2085- {
2086- plugin_manager();
2087- load_all(loadpath);
2088- };
2089-
2090- plugin_manager::~plugin_manager()
2091- {
2092- release_all();
2093- };
2094-
2095- void plugin_manager::load_all(const boost::filesystem::path loadpath)
2096- {
2097- // check to if loadpath really exists
2098- if (!boost::filesystem::exists(loadpath))
2099- {
2100- path_not_found e;
2101- e.store(loadpath.native_directory_string());
2102- throw e;
2103- };
2104- if (!is_directory(loadpath))
2105- {
2106- not_a_directory e;
2107- e.store(loadpath.native_file_string());
2108- throw e;
2109- };
2110- // set up for the scan
2111- boost::filesystem::directory_iterator end; // points to the end of the list
2112- boost::filesystem::directory_iterator current(loadpath);
2113- while (current != end)
2114- {
2115- if (is_directory(*current))
2116- {
2117- // recursive call to process the directory.
2118- load_all(*current);
2119- }
2120- else
2121- {
2122- // try to load the plugin
2123- try
2124- {
2125- load_one(*current);
2126- }
2127- catch (plugin_wrapper::invalid_plugin & e)
2128- {
2129- // take no action in this caee...
2130- };
2131- };
2132- current++;
2133- };
2134- };
2135-
2136- void plugin_manager::load_one(const boost::filesystem::path loadpath)
2137- {
2138- // check to if loadpath really exists
2139- if (!boost::filesystem::exists(loadpath))
2140- {
2141- path_not_found e;
2142- e.store(loadpath.native_directory_string());
2143- throw e;
2144- };
2145- if (boost::filesystem::is_directory(loadpath))
2146- {
2147- plugin_file_not_found e;
2148- e.store(loadpath.native_file_string());
2149- throw e;
2150- };
2151- /* NOTE: since wrapper_p is a smart pointer, any memory
2152- allocated to it will be discarded if an exception
2153- is thrown in the following section.
2154- */
2155- // Create the plugin_wrapper.
2156- wrapper_p new_plugin(new plugin_wrapper);
2157- // Load it... will throw if somehing's not right.
2158- new_plugin->load(loadpath);
2159- // Store it in our list.
2160- plugins[new_plugin->get_type()][new_plugin->get_name()] = new_plugin;
2161- };
2162-
2163- void plugin_manager::release_all()
2164- {
2165- // this will call the destructor and deallocate all
2166- // plugin_wrappers currently loaded.
2167- plugins.clear();
2168- };
2169-
2170- void plugin_manager::release_one(const std::string pclass,
2171- const std::string name)
2172- {
2173- // TODO: more here.
2174- plugins[pclass].erase(name);
2175- };
2176-
2177- std::string plugin_manager::dump()
2178- {
2179- // TODO: More to do here.
2180- };
2181-
2182-}; // namespace NRTB
2183-
2184
2185=== removed file 'common/plugin_loader/plugin_manager.h'
2186--- common/plugin_loader/plugin_manager.h 2010-01-14 02:24:25 +0000
2187+++ common/plugin_loader/plugin_manager.h 1970-01-01 00:00:00 +0000
2188@@ -1,194 +0,0 @@
2189-//
2190-// C++ Interface: plugin_manager
2191-//
2192-// Description:
2193-//
2194-//
2195-// Author: Rick Stovall <rstovall@gabbie>, (C) 2008
2196-//
2197-// Copyright: See COPYING file that comes with this distribution
2198-//
2199-//
2200-
2201-#ifndef plugin_manager_h
2202-#define plugin_manager_h
2203-
2204-#include "plugin_wrapper.h"
2205-#include <map>
2206-
2207-namespace NRTB
2208-{
2209- /**
2210- * Provides a simple mechanism for an application to
2211- * load and manage plugins (shared objects in the unix lingo)
2212- * which provide the application with functionality not
2213- * not available at the time it was built.
2214- *
2215- * To be useable with this class a shared object must
2216- * meet certain requirements which are outlined in the
2217- * NRTB::plugin_wrapper class documentation. Example
2218- * plugins are also provided.
2219- */
2220- class plugin_manager
2221- {
2222- public:
2223- /// Typedef for return values
2224- typedef std::vector<std::string> strlist;
2225- /// parent for all exceptions thrown by this class
2226- class general_exception: public base_exception {};
2227- /// thrown if a specified plugin file was no found.
2228- class plugin_file_not_found: public general_exception {};
2229- /// thrown if a specified load path (directory) was not found.
2230- class path_not_found: public general_exception {};
2231- /// thown if a specified load path is not a directory.
2232- class not_a_directory: public general_exception {};
2233- /// thrown if a specifically requested plugin is not loaded.
2234- class plugin_not_found: public general_exception {};
2235- /**
2236- * Simple constructor.
2237- */
2238- plugin_manager();
2239- /**
2240- * Constructs the class and then attempts to load all
2241- * files found under the given path (recursively) as
2242- * plugins.Non-plugin files will be ignored, but
2243- * problems reading the given path (path not found,
2244- * insufficient permissions, etc.) will cause an
2245- * exception to be thrown.
2246- *
2247- * @param loadpath The top of the file tree to be searched.
2248- */
2249- plugin_manager(const boost::filesystem::path loadpath);
2250- /**
2251- * Unloads all managed plugins and destructs the
2252- * plugin_manager. Probably not a good thing to do
2253- * while any of the plugins are in use.
2254- */
2255- virtual ~plugin_manager();
2256- /**
2257- * Attempts to load all files found under the
2258- * given path (recursively) as plugins.Non-plugin
2259- * files will be ignored, but problems reading the
2260- * given path (path not found, insufficient
2261- * permissions, etc.) will cause an exception to be thrown.
2262- *
2263- * If two plugins have the same class and name, the one
2264- * with the highest version number will be kept and
2265- * the other(s) discarded.
2266- *
2267- * @param loadpath The top of the file tree to be searched.
2268- */
2269- void load_all(const boost::filesystem::path loadpath);
2270- /**
2271- * Attempts to load a plugin from the fully qualified
2272- * file path given. Exceptions will be thrown if there
2273- * are any problems reading the file, or if it is not a
2274- * valid plugin (by plugin_wrapper standards).
2275- *
2276- * If two plugins have the same class and name, the one
2277- * with the highest version number will be kept and
2278- * the other(s) discarded.
2279- *
2280- * @param loadpath A fully qualified file path.
2281- */
2282- void load_one(const boost::filesystem::path loadpath);
2283- /**
2284- * Releases all plugins currently being managed. Probably
2285- * not a good thing to do if any of them are being used.
2286- */
2287- void release_all();
2288- /**
2289- * Attempts to release the single plugin matching the
2290- * provided plugin class and name. An exception will be thrown
2291- * if the plugin is not found.
2292- *
2293- * @param pclass The class of the plugin to release.
2294- * @param name The name of the plugin to release.
2295- */
2296- void release_one(const std::string pclass, const std::string name);
2297- /**
2298- * Dumps a list of all loaded plugins, intended for
2299- * diagnostic purposes. The list is formatted:
2300- *
2301- * plugin_class::plugin_name<eol>
2302- *
2303- * with one line for each plugin loaded.
2304- *
2305- * @return A string contianing a formatted plugin listing.
2306- */
2307- std::string dump();
2308- /**
2309- * Returns a strlist (a vector<string>) containing
2310- * all unique plugin class names loaded, in alpha order.
2311- *
2312- * @return A list of all unique plugin classes loaded.
2313- */
2314- strlist get_class_names();
2315- /**
2316- * Returns a strlist (a vector<string>) containing
2317- * the names of all plugins loaded of the given plugin class.
2318- *
2319- * @param pclass The name of the plugin class to be searched.
2320- * @return A list of all plugins loaded for the given plugin class.
2321- */
2322- strlist get_class_plugin_names(const std::string pclass);
2323- /**
2324- * Returns true if a plugin with the given class
2325- * and name exists, or faise if not.
2326- *
2327- * @param pclass The class name of the plugin to be checked.
2328- * @param pname The name of the plugin to be checked
2329- * @return True if the plugin is laoded, false otherwise.
2330- */
2331- bool exists(const std::string pclass, const std::string pname);
2332- /**
2333- * Returns a boost::shared_ptr<T> to a new instance
2334- * of the class provided by the plugin specified by
2335- * the plugin_class and plugin_name provided.
2336- *
2337- * Usage example:
2338- * myTypePointer = create_plugin_instance<mytype>(class,name);
2339- *
2340- * This routine will succeed unconditionally or throw
2341- * one of several possible exceptions. In no case will a
2342- * null pointer or improperly constructed instance be
2343- * returned.
2344- *
2345- * @param plugin_class The class name of the plugin desired
2346- * @param plugin_name The name of the plugin desired.
2347- * @return A boost::shared_ptr<T> to a ready to use instance.
2348- */
2349- template <class T> boost::shared_ptr<T> create_plugin_instance
2350- (
2351- const std::string plugin_class,
2352- const std::string plugin_name
2353- )
2354- {
2355- typedef boost::shared_ptr<T> returntype;
2356- if (!exists(plugin_class, plugin_name))
2357- {
2358- plugin_not_found e;
2359- e.store(plugin_class+"::"+plugin_name);
2360- throw e;
2361- };
2362- returntype returnme =
2363- plugins[plugin_class][plugin_name]->create_instance<T>();
2364- return returnme;
2365- };
2366- protected:
2367- // smart pointer to a plugin_wrapper
2368- typedef boost::shared_ptr<plugin_wrapper> wrapper_p;
2369- // type used contain plugins of the same type
2370- typedef std::map<std::string, wrapper_p> plugins_by_name;
2371- // type used to contain lists of types of plugins.
2372- typedef std::map<std::string, plugins_by_name> plugins_list_by_class;
2373- // iterator providing access to "plugins_by_name" lists by class
2374- typedef plugins_list_by_class::iterator class_iterator;
2375- // iterator providing access to individual plugins by name
2376- typedef plugins_by_name::iterator plugin_iterator;
2377- // container for all plugins being managed.
2378- plugins_list_by_class plugins;
2379- };
2380-};
2381-
2382-#endif //plugin_manager_h
2383
2384=== removed file 'common/plugin_loader/plugin_wrapper.cpp'
2385--- common/plugin_loader/plugin_wrapper.cpp 2010-01-14 02:24:25 +0000
2386+++ common/plugin_loader/plugin_wrapper.cpp 1970-01-01 00:00:00 +0000
2387@@ -1,146 +0,0 @@
2388-//
2389-// C++ Implementation: plugin_wrapper
2390-//
2391-// Description:
2392-//
2393-//
2394-// Author: Rick Stovall <rstovall@gabbie>, (C) 2008
2395-//
2396-// Copyright: See COPYING file that comes with this distribution
2397-//
2398-//
2399-
2400-#include "plugin_wrapper.h"
2401-
2402-namespace NRTB
2403-{
2404-
2405- plugin_wrapper::plugin_wrapper()
2406- {
2407- // Load the "constants"
2408- std::string name_key = "PLUGIN_NAME";
2409- std::string type_key = "PLUGIN_TYPE";
2410- std::string version_key = "PLUGIN_VERSION";
2411- std::string factory_key = "PLUGIN_FACTORY";
2412- // clear all the associated fields.
2413- plugin_type = "";
2414- plugin_name = "";
2415- plugin_version = 0.0;
2416- plugin_path = "";
2417- // close the handle if it's already assigned.
2418- if (dl_handle)
2419- {
2420- dlclose(dl_handle);
2421- };
2422- dl_handle = 0;
2423- };
2424-
2425- plugin_wrapper::plugin_wrapper(boost::filesystem::path loadpath)
2426- {
2427- load(loadpath);
2428- };
2429-
2430- plugin_wrapper::~plugin_wrapper()
2431- {
2432- // close the handle if it's already assigned.
2433- if (dl_handle)
2434- {
2435- dlclose(dl_handle);
2436- };
2437- dl_handle = 0;
2438- };
2439-
2440- void plugin_wrapper::load(boost::filesystem::path loadpath)
2441- {
2442- // establish initial conditions.
2443- plugin_wrapper();
2444- if (loadpath.empty())
2445- {
2446- // an empty path could expose security holes.
2447- file_not_found e;
2448- e.store("Illegal null path provided");
2449- throw e;
2450- };
2451- dlerror();
2452- try
2453- {
2454- // call dlopen to open the lib
2455- dl_handle = dlopen(loadpath.string().c_str(), RTLD_LAZY);
2456- if (!dl_handle)
2457- {
2458- throw new file_not_found;
2459- };
2460- // load the fields
2461- plugin_type = get_value<std::string>(type_key);
2462- plugin_name = get_value<std::string>(name_key);
2463- plugin_version = get_value<float>(version_key);
2464- plugin_path = loadpath;
2465- }
2466- catch (file_not_found &e)
2467- {
2468- // is it a missing file or a bad file?
2469- if (!boost::filesystem::exists(loadpath))
2470- {
2471- e.store(loadpath.string());
2472- throw e;
2473- }
2474- else
2475- {
2476- invalid_plugin ie;
2477- ie.store(dlerror());
2478- throw ie;
2479- };
2480- }
2481- catch (invalid_plugin & e)
2482- {
2483- if (e.comment() == "")
2484- {
2485- e.store(dlerror());
2486- };
2487- throw e;
2488- }
2489- catch (std::exception &e)
2490- {
2491- general_exception ge;
2492- ge.store(e.what());
2493- throw ge;
2494- };
2495- };
2496-
2497- std::string plugin_wrapper::get_type()
2498- {
2499- if (!dl_handle)
2500- {
2501- throw new not_loaded;
2502- };
2503- return plugin_type;
2504- };
2505-
2506- std::string plugin_wrapper::get_name()
2507- {
2508- if (!dl_handle)
2509- {
2510- throw new not_loaded;
2511- };
2512- return plugin_name;
2513- };
2514-
2515- float plugin_wrapper::get_version()
2516- {
2517- if (!dl_handle)
2518- {
2519- throw new not_loaded;
2520- };
2521- return plugin_version;
2522- };
2523-
2524- boost::filesystem::path plugin_wrapper::get_path()
2525- {
2526- if (!dl_handle)
2527- {
2528- throw new not_loaded;
2529- };
2530- return plugin_path;
2531- };
2532-
2533-} // namespace NRTB
2534
2535=== removed file 'common/plugin_loader/plugin_wrapper.h'
2536--- common/plugin_loader/plugin_wrapper.h 2010-01-14 02:24:25 +0000
2537+++ common/plugin_loader/plugin_wrapper.h 1970-01-01 00:00:00 +0000
2538@@ -1,207 +0,0 @@
2539-//
2540-// C++ Interface: plugin_wrappr
2541-//
2542-// Description:
2543-//
2544-//
2545-// Author: Rick Stovall <rstovall@gabbie>, (C) 2008
2546-//
2547-// Copyright: See COPYING file that comes with this distribution
2548-//
2549-//
2550-
2551-#ifndef plugin_wrapper_h
2552-#define plugin_wrapper_h
2553-
2554-#include <dlfcn.h>
2555-#include <string>
2556-#include <ricks_handy.h>
2557-#include <boost/shared_ptr.hpp>
2558-#include <boost/filesystem/convenience.hpp>
2559-
2560-namespace NRTB
2561-{
2562- /**
2563- * A container for a single plugin. A plugin is defined as a
2564- * shared object file which provides a class, an associated factory
2565- * function, and several housekeeping constants, as follows:
2566- *
2567- * 1. A std::string identifying the class factory named "PLUGIN_FACTORY"
2568- *
2569- * 2. A plugin name std::string named "PLUGIN_NAME"
2570- *
2571- * 3. A plugin type std::stirng named "PLUGIN_TYPE"
2572- *
2573- * 4. A plugin version number float named "PLUGIN_VERSION"
2574- *
2575- * This class is not designed to instanticated directly by user code.
2576- * Instead, it will be intanciated by the plugin_manager, which acts as
2577- * a container for many plugins and provides access to them.
2578- *
2579- * In call cases except load(), when an exception is thown from a method,
2580- * the instance is left the state it was in at the start of the method.
2581- **/
2582- class plugin_wrapper
2583- {
2584- public:
2585- /// Parent for all plugin_wrapper exceptions.
2586- class general_exception: public base_exception {};
2587- /// Thrown if a file is not found at the requested path.
2588- class file_not_found: public general_exception {};
2589- /// Thrown if a requested file does not contain a valid plugin.
2590- class invalid_plugin: public general_exception {};
2591- /// Thrown if queries are called when no data is present.
2592- class not_loaded: public general_exception {};
2593- /**
2594- * Default constructor; NOP.
2595- */
2596- plugin_wrapper();
2597- /**
2598- * This constructor attempts to load a plugin at
2599- * the argument provided. Actually calls load() to
2600- * to do the work.
2601- *
2602- * @param loadpath Should be point to a valid plugin file
2603- */
2604- plugin_wrapper(boost::filesystem::path loadpath);
2605- /**
2606- * Unloads any plugin, if contained.
2607- */
2608- virtual ~plugin_wrapper();
2609- /**
2610- * Discards the current contents of this wrapper, if any,
2611- * and then attempts to load the plugin file provided. If there
2612- * are any problems, an appropriate exception will be thrown.
2613- *
2614- * @param loadpath Should point to a valid plugin file.
2615- */
2616- virtual void load(boost::filesystem::path loadpath);
2617- /**
2618- * Returns the pligin type associated with the loaded plugin,
2619- * or throws if one is not loaded. The plugin type is a string
2620- * indicating the what services the plugin provides and in
2621- * most cases will have no meaning outside of the application
2622- * context.
2623- *
2624- * For example, a plugin providing printing functionality
2625- * may have a type of "printer", while one that provides
2626- * database access may have a type of "db_interface".
2627- *
2628- * @return A std::string indicating plugin type.
2629- */
2630- virtual std::string get_type();
2631- /**
2632- * Returns the name of the particular plugin loaded, or
2633- * throws if one is not loaded. The name is an arbitrary string
2634- * which uniquely identifies a particular plugin within a type.
2635- *
2636- * For example, a plugin providing printing functionality to
2637- * a PDF file may have a type of "printer" and a name of "PDF",
2638- * while another "printer" plugin providing output to doc
2639- * files may have the name "WordDoc".
2640- *
2641- * @return A std::string indicating the plugin name.
2642- */
2643- virtual std::string get_name();
2644- /**
2645- * Returns the version of the particular plugin loaded, or
2646- * throws if one is not loaded. The version is an arbitrary
2647- * float value which uniquely identifies a particular version
2648- * of a plugin within a name and type.
2649- *
2650- * @return A float indicating the plugin version.
2651- */
2652- virtual float get_version();
2653- /**
2654- * Returns the fully qualified path of the plugin loaded, or
2655- * throws if one is not loaded.
2656- *
2657- * @return A boost::filesystem::path to the plugin file.
2658- */
2659- boost::filesystem::path get_path();
2660- /**
2661- * Calls the class factory and returns shared_ptr to an
2662- * instance of the type requested. For reliable operation,
2663- * the type provided the template must be compatable with
2664- * that actually implemented in the plugin.
2665- *
2666- * An appropriate exception will be thrown if there are issues.
2667- *
2668- * Usage: mytype myvar createInstance<mytype>();
2669- *
2670- * @return A boost::shared_ptr to an instanace of
2671- * the type provided.
2672- */
2673- template <class T> boost::shared_ptr<T> create_instance()
2674- {
2675- if (!dl_handle)
2676- {
2677- not_loaded e;
2678- e.store("create_instance");
2679- throw e;
2680- };
2681- typedef T (*factory_type)();
2682- typedef boost::shared_ptr<T> my_pointer;
2683- my_pointer returnme;
2684- try
2685- {
2686- factory_type factory = get_value<factory_type>(factory_key);
2687- returnme = factory();
2688- }
2689- catch (std::exception & e)
2690- {
2691- // Let the caller sort it out.
2692- throw;
2693- }
2694- catch (...)
2695- {
2696- // most likely a bad problem in the factory function.
2697- invalid_plugin e;
2698- e.store("create_instance caught an unknown exception");
2699- throw e;
2700- };
2701- return returnme;
2702- };
2703-
2704- protected:
2705- // gets indivdual field values from the shared lib.
2706- template <class T> T get_value(const std::string & key)
2707- {
2708- typedef T * my_pointer;
2709- T returnme;
2710- dlerror();
2711- my_pointer value = (my_pointer) dlsym(dl_handle,key.c_str());
2712- std::string check_error = dlerror();
2713- if (!check_error.empty())
2714- {
2715- invalid_plugin e;
2716- e.store(check_error+" ("+key+")");
2717- throw e;
2718- };
2719- if (!value)
2720- {
2721- invalid_plugin e;
2722- e.store("("+key+") returned a null value");
2723- throw e;
2724- };
2725- returnme = *value;
2726- return returnme;
2727- };
2728-
2729- private:
2730- // The following are used to cache plugin data after load.
2731- void * dl_handle;
2732- std::string plugin_type;
2733- std::string plugin_name;
2734- float plugin_version;
2735- boost::filesystem::path plugin_path;
2736- // The following define what labels are expected to be defined.
2737- static const std::string name_key;
2738- static const std::string type_key;
2739- static const std::string version_key;
2740- static const std::string factory_key;
2741- };
2742-
2743-} // nameplace NRTB
2744-
2745-#endif // plugin_wrapper_h
2746
2747=== removed directory 'common/plugin_loader/test'
2748=== removed file 'common/plugin_loader/test/Makefile'
2749--- common/plugin_loader/test/Makefile 2010-01-14 02:24:25 +0000
2750+++ common/plugin_loader/test/Makefile 1970-01-01 00:00:00 +0000
2751@@ -1,13 +0,0 @@
2752-
2753-# makefile for the plugin test routine.
2754-
2755-test: ../plugin_wrapper.o ../plugin_manager.o plugintest.cpp
2756- @rm -f plugintest
2757- g++ -c plugintest.cpp -idirafter ../../include3 -idirafter /usr/local/include/boost-1_31
2758-# g++ -c -g conftest.cpp -idirafter ../../include3 -idirafter /usr/local/include/boost-1_31
2759- g++ -o plugintest plugintest.o ../plugin_wrapper.o ../plugin_manager.o -l ricklib3 -L../../lib/
2760- ./plugintest
2761-
2762-clean:
2763- @rm -rvf *.o plugintest
2764- @echo all objects and executables have been erased.
2765
2766=== removed directory 'common/plugin_loader/test/plugins'
2767=== removed file 'common/plugin_loader/test/plugintest.cpp'
2768--- common/plugin_loader/test/plugintest.cpp 2010-01-14 02:24:25 +0000
2769+++ common/plugin_loader/test/plugintest.cpp 1970-01-01 00:00:00 +0000
2770@@ -1,12 +0,0 @@
2771-//
2772-// C++ Implementation: plugintest
2773-//
2774-// Description:
2775-//
2776-//
2777-// Author: Rick Stovall <rstovall@gabbie>, (C) 2008
2778-//
2779-// Copyright: See COPYING file that comes with this distribution
2780-//
2781-//
2782-
2783
2784=== modified file 'common/point/Makefile'
2785--- common/point/Makefile 2010-01-14 02:24:25 +0000
2786+++ common/point/Makefile 2011-08-25 04:57:16 +0000
2787@@ -1,17 +1,34 @@
2788-build: common_test Makefile
2789- @echo build complete
2790-
2791-common_test: common_test.cpp triad.h Makefile
2792- @rm -vf triad.o
2793- g++ -O3 common_test.cpp -idirafter . -o common_test
2794-# g++ -g common_test.cpp -idirafter . -o common_test
2795+#***********************************************
2796+#This file is part of the NRTB project (https://launchpad.net/nrtb).
2797+#
2798+# NRTB is free software: you can redistribute it and/or modify
2799+# it under the terms of the GNU General Public License as published by
2800+# the Free Software Foundation, either version 3 of the License, or
2801+# (at your option) any later version.
2802+#
2803+# NRTB is distributed in the hope that it will be useful,
2804+# but WITHOUT ANY WARRANTY; without even the implied warranty of
2805+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2806+# GNU General Public License for more details.
2807+#
2808+# You should have received a copy of the GNU General Public License
2809+# along with NRTB. If not, see <http://www.gnu.org/licenses/>.
2810+#
2811+#***********************************************
2812+
2813+lib: common_test Makefile
2814+ @echo "(2,3.5,7)" | ./common_test
2815+ @cp -v triad.h ../include
2816+ @echo nrtb::triad build complete
2817+
2818+../include/common.h:
2819+ @cd ../common_rl; make lib
2820+
2821+common_test: common_test.cpp triad.h Makefile ../include/common.h
2822+ @rm -vf common_test
2823+ g++ -O3 common_test.cpp -I ../include ../obj/common.o -o common_test
2824
2825 clean:
2826- @rm -vf *.o common_test ../../include3/triad.h
2827-
2828-lib: common_test ../../include3/triad.h
2829-
2830-../../include3/triad.h: triad.h
2831- @cp -fv triad.h ../../include3
2832+ @rm -vf *.o common_test ../include/triad.h
2833
2834
2835
2836=== modified file 'common/point/common_test.cpp'
2837--- common/point/common_test.cpp 2010-01-14 02:24:25 +0000
2838+++ common/point/common_test.cpp 2011-08-25 04:57:16 +0000
2839@@ -1,4 +1,22 @@
2840-/*** Test program for triad.h *****/
2841+/***********************************************
2842+ This file is part of the NRTB project (https://*launchpad.net/nrtb).
2843+
2844+ NRTB is free software: you can redistribute it and/or modify
2845+ it under the terms of the GNU General Public License as published by
2846+ the Free Software Foundation, either version 3 of the License, or
2847+ (at your option) any later version.
2848+
2849+ NRTB is distributed in the hope that it will be useful,
2850+ but WITHOUT ANY WARRANTY; without even the implied warranty of
2851+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2852+ GNU General Public License for more details.
2853+
2854+ You should have received a copy of the GNU General Public License
2855+ along with NRTB. If not, see <http://www.gnu.org/licenses/>.
2856+
2857+ **********************************************/
2858+
2859+ /*** Test program for triad.h *****/
2860
2861 #include <unistd.h>
2862 #include <iostream>
2863@@ -7,56 +25,93 @@
2864
2865 using namespace std;
2866
2867-typedef NRTB::triad<long double> ld_triad;
2868+typedef nrtb::triad<long double> ld_triad;
2869+
2870+int test_triad(const std::string prompt, ld_triad val, ld_triad right, int ec)
2871+{
2872+ cout << "\t" << prompt << " = " << val << endl;
2873+ if (val != right)
2874+ {
2875+ ec++;
2876+ cerr << "\t\tTest Failed: Answer should be " << val << endl;
2877+ }
2878+ return ec;
2879+};
2880+
2881+int test_ld(const std::string prompt, long double val, long double right, int ec)
2882+{
2883+ cout << "\t" << prompt << " = " << val << endl;
2884+ if (val != right)
2885+ {
2886+ ec++;
2887+ cerr << "\t\tTest Failed: Answer should be " << val << endl;
2888+ }
2889+ return ec;
2890+};
2891
2892 int main()
2893 {
2894 ld_triad a(1,2,3);
2895 ld_triad b(3,2,1);
2896+ int returnme = 0;
2897
2898 cout << setprecision(10);
2899- cout << "=== Triad Test ===" << endl;
2900- cout << "\ta = " << a << "; b = " << b << "\n" << endl;
2901-
2902- cout << "\ta + b = " << a + b << endl;
2903- cout << "\ta - b = " << a - b << endl;
2904- cout << "\ta * b = " << a * b << endl;
2905- cout << "\ta / b = " << a / b << endl;
2906- cout << "\ta += b; a = " << (a += b) << endl;
2907- cout << "\ta -= b; a = " << (a -= b) << endl;
2908- cout << "\ta *= b; a = " << (a *= b) << endl;
2909- cout << "\ta /= b; a = " << (a /= b) << endl;
2910- cout << "\n\ta.pow(b) = " << a.pow(b) << endl;
2911- cout << "\ta.range(b) = " << a.range(b) << endl;
2912- cout << "\ta.magnatude() = " << a.magnatude() << endl;
2913- cout << "\n\ta == a = " << (a == a) << endl;
2914- cout << "\ta == b = " << (a== b) << endl;
2915- cout << "\ta != b = " << (a != b) << endl;
2916- cout << "\ta != a = " << (a != a) << endl;
2917-
2918- cout << endl;
2919-
2920- cout << "\ta + 2 = " << a + 2 << endl;
2921- cout << "\ta - 2 = " << a - 2 << endl;
2922- cout << "\ta * 2 = " << a * 2 << endl;
2923- cout << "\ta / 2 = " << a / 2 << endl;
2924- cout << "\ta += 2; a = " << (a += 2) << endl;
2925- cout << "\ta -= 2; a = " << (a -= 2) << endl;
2926- cout << "\ta *= 2; a = " << (a *= 2) << endl;
2927- cout << "\ta /= 2; a = " << (a /= 2) << endl;
2928- cout << "\n\ta.pow(2) = " << a.pow(2) << endl;
2929- cout << "\ta.pow(0.5) = " << a.pow(0.5) << endl;
2930+ cout << "=== nrtb::triad Unit Test ===" << endl;
2931+ cout << "\ta = " << a << "; b = " << b << endl;
2932+ // basic operations tests
2933+ returnme = test_triad("a + b",a + b,ld_triad(4,4,4),returnme);
2934+ returnme = test_triad("a - b",a - b,ld_triad(-2,0,2),returnme);
2935+ returnme = test_triad("a * b",a * b,ld_triad(3,4,3),returnme);
2936+ returnme = test_triad("a / b",a / b,ld_triad(1.0d/(long double) 3.0,1,3),returnme);
2937+ returnme = test_triad("a += b; a",a += b,ld_triad(4,4,4),returnme);
2938+ returnme = test_triad("a -= b; a",a -= b,ld_triad(1,2,3),returnme);
2939+ returnme = test_triad("a *= b; a",a *= b,ld_triad(3,4,3),returnme);
2940+ returnme = test_triad("a /= b; a",a /= b,ld_triad(1,2,3),returnme);
2941+ // power test
2942+ returnme = test_triad("a.pow(b)",a.pow(b),ld_triad(1,4,3),returnme);
2943+ // range test
2944+ ld_triad t = b - a;
2945+ t *= t;
2946+ long double r = sqrt(t.x + t.y + t.z);
2947+ returnme = test_ld("a.range(b)",a.range(b),r,returnme);
2948+ // magnatude test
2949+ returnme = test_ld("a.magnatude()",a.magnatude(),a.range(0),returnme);
2950+ // boolean tests
2951+ returnme = test_ld("a == a",a == a,1,returnme);
2952+ returnme = test_ld("a == b",a == b,0,returnme);
2953+ returnme = test_ld("a != b",a != b,1,returnme);
2954+ returnme = test_ld("a != a",a != a,0,returnme);
2955+ // point/scalar operations
2956+ returnme = test_triad("a + 2",a + 2,ld_triad(3,4,5),returnme);
2957+ returnme = test_triad("a - 2",a - 2,ld_triad(-1,0,1),returnme);
2958+ returnme = test_triad("a * 2",a * 2,ld_triad(2,4,6),returnme);
2959+ returnme = test_triad("a / 2",a / 2,ld_triad(0.5,1,1.5),returnme);
2960+ returnme = test_triad("a += 2",a += 2,ld_triad(3,4,5),returnme);
2961+ returnme = test_triad("a -= 2",a -= 2,ld_triad(1,2,3),returnme);
2962+ returnme = test_triad("a *= 2",a *= 2,ld_triad(2,4,6),returnme);
2963+ returnme = test_triad("a /= 2",a /= 2,ld_triad(1,2,3),returnme);
2964+ returnme = test_triad("a.pow(2)",a.pow(2),ld_triad(1,4,9),returnme);
2965+ // normalization test
2966 cout << "\ta.normalize() = " << a.normalize() << endl;
2967- cout << "\ta.normalize().magnatude() = "<< a.normalize().magnatude() << endl;
2968-
2969- cout << "\n\a\tInput a new value for b (x,y,z): " << flush;
2970- cin >> b;
2971- cout << "\t\tb = " << b << endl;
2972- cout << "\tb.to_str() =\"" << b.to_str() << "\"" << endl;
2973- cout << "\tb.from_str(b.to_str(10)) = " << b.from_str(b.to_str(10)) << endl;
2974-
2975-
2976- cout << "\n=== Test Complete ===" << endl;
2977- return 0;
2978+ returnme = test_ld("a.normalize().magnatude()",a.normalize().magnatude(),1.0,returnme);
2979+ // dot and vector product tests.
2980+ returnme = test_ld("a.dot_product(b)",a.dot_product(b),10,returnme);
2981+ returnme = test_triad("a.vector_product(b)",a.vector_product(b),
2982+ ld_triad(-4,8,-4),returnme);
2983+ // string i/o tests, assumes "2,3.5,7) is input.
2984+ cout << "\tInput a new value for b \"(2,3.5,7)\": " << flush;
2985+ cin >> b; cout << endl;
2986+ returnme = test_triad("b",b,ld_triad(2,3.5,7),returnme);
2987+ returnme = test_triad("b.from_str(b.to_str(10))",
2988+ b.from_str(b.to_str(10)),ld_triad(2,3.5,7),returnme);
2989+ // report errors, if any
2990+ if (returnme)
2991+ {
2992+ cerr << "There were " << returnme
2993+ << " error(s) found." << endl;
2994+ }
2995+ cout << "=== nrtb::triad Unit Test Complete ===" << endl;
2996+ // return the error count as the exit code
2997+ return returnme;
2998
2999 };
3000
3001=== modified file 'common/point/triad.h'
3002--- common/point/triad.h 2010-01-14 02:24:25 +0000
3003+++ common/point/triad.h 2011-08-25 04:57:16 +0000
3004@@ -1,31 +1,40 @@
3005-/*************************************************************
3006-**** CODE REVIEW: triad.h, starting 2008-11-24 ***************
3007-* The triad template is fully implemented in this one file.
3008-* This class will be used for all vector and point operations
3009-* Please make any comments or suggestions directly in the file.
3010-*************************************************************/
3011-
3012-/**************************************************
3013-TODO: add methods for dot product, cross multiply,
3014- finding the surface normal, etc.
3015-/**************************************************
3016-
3017-#ifndef nrtb_triad_header
3018-#define nrtb_triad_header
3019+/***********************************************
3020+ This file is part of the NRTB project (https://*launchpad.net/nrtb).
3021+
3022+ NRTB is free software: you can redistribute it and/or modify
3023+ it under the terms of the GNU General Public License as published by
3024+ the Free Software Foundation, either version 3 of the License, or
3025+ (at your option) any later version.
3026+
3027+ NRTB is distributed in the hope that it will be useful,
3028+ but WITHOUT ANY WARRANTY; without even the implied warranty of
3029+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3030+ GNU General Public License for more details.
3031+
3032+ You should have received a copy of the GNU General Public License
3033+ along with NRTB. If not, see <http://www.gnu.org/licenses/>.
3034+
3035+ **********************************************/
3036+
3037+#ifndef triad_header
3038+#define triad_header
3039
3040 #include <iostream>
3041+#include <vector>
3042+#include <string>
3043 #include <sstream>
3044 #include <iomanip>
3045 #include <math.h>
3046+#include <common.h>
3047
3048-namespace NRTB
3049+namespace nrtb
3050 {
3051
3052 /** Template defining a point or vector in cartesian 3d space. Should work
3053 ** with all floating point types.
3054 **
3055 ** Implements the following operators: +,=,*,/,+=,-=,*=,/= for both
3056- ** triad<T> and <T> arguments; each returns a triad as the result.
3057+ ** triad<T> and <T> arguments; each returns an triad as the result.
3058 ** ==,!=,>>,<< are implemented for triad arguments. Additionally
3059 ** implements pow() with triad and T arguments. Finally implements range()
3060 ** which returns the distance between the triad and one supplied, and
3061@@ -76,13 +85,17 @@
3062 ** is not modified.
3063 **
3064 ** Normalized triads are very useful when calcuating force or
3065- ** accelleration vectors and in many other cases.
3066+ ** accelleration vectors, for example.
3067 **/
3068 triad<T> normalize();
3069 /// Returns the distance between *this and the supplied argument.
3070 T range(const triad<T> & a);
3071 /// Returns the magnatude of the vector.
3072 T magnatude();
3073+ /// Returns the dot (scalar) product of two triads
3074+ T dot_product(const triad<T> & a);
3075+ /// Returns the vector product of two triads
3076+ triad<T> vector_product(const triad<T> & a);
3077 bool operator == (const triad<T> & a);
3078 bool operator != (const triad<T> & a);
3079 /// Loads from a std::string.
3080@@ -292,6 +305,26 @@
3081 };
3082
3083 template <class T>
3084+T triad<T>::dot_product(const triad<T> & a)
3085+{
3086+ T returnme;
3087+ returnme = x * a.x;
3088+ returnme += y * a.y;
3089+ returnme += z * a.z;
3090+ return returnme;
3091+};
3092+
3093+template <class T>
3094+triad<T> triad<T>::vector_product(const triad<T> & a)
3095+{
3096+ triad<T> rv;
3097+ rv.x = (y * a.z) - (z * a.y);
3098+ rv.y = (z * a.x) - (x * a.z);
3099+ rv.z = (x * a.y) - (y * a.x);
3100+ return rv;
3101+};
3102+
3103+template <class T>
3104 bool triad<T>::operator == (const triad<T> & a)
3105 {
3106 return ((x == a.x) && (y == a.y) && (z == a.z));
3107@@ -329,16 +362,11 @@
3108 return f;
3109 };
3110
3111- //?? Review question: should we have the read operator
3112- // throw instead of defaulting to (0,0,0) on a bad read?
3113- // A: No, because this is the same behavior the read
3114- // operator exhibits with other numeric types.
3115-
3116 /** Reads the triad<T> from an input stream.
3117 **
3118 ** The acceptable format is [(]x,y,z[)]. Any other format will result
3119 ** in the triad<T> being set to (0,0,0). Any numeric format acceptable
3120- ** to an iostream is valid for x, y and z. Any other represention of x,
3121+ ** to strtod() is valid for x, y and z. Any other represention of x,
3122 ** y or z will result in that particular value being set to 0.
3123 **/
3124 template <class T>
3125@@ -346,8 +374,7 @@
3126 {
3127 std::string element;
3128 f >> element;
3129- //TODO: Need to replace split with boost equivelent
3130- std::vector<std::string> t = split(element,',');
3131+ strlist t = split(element,',');
3132 if (t.size() != 3)
3133 {
3134 a = 0;
3135@@ -363,6 +390,6 @@
3136 return f;
3137 };
3138
3139-} // namespace NRTB
3140+} // namespace nrtb
3141
3142-#endif // nrtb_triad_header
3143+#endif // triad_header
3144
3145=== added directory 'common/serializer'
3146=== added file 'common/serializer/Makefile'
3147--- common/serializer/Makefile 1970-01-01 00:00:00 +0000
3148+++ common/serializer/Makefile 2011-08-25 04:57:16 +0000
3149@@ -0,0 +1,36 @@
3150+#***********************************************
3151+#This file is part of the NRTB project (https://launchpad.net/nrtb).
3152+#
3153+# NRTB is free software: you can redistribute it and/or modify
3154+# it under the terms of the GNU General Public License as published by
3155+# the Free Software Foundation, either version 3 of the License, or
3156+# (at your option) any later version.
3157+#
3158+# NRTB is distributed in the hope that it will be useful,
3159+# but WITHOUT ANY WARRANTY; without even the implied warranty of
3160+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3161+# GNU General Public License for more details.
3162+#
3163+# You should have received a copy of the GNU General Public License
3164+# along with NRTB. If not, see <http://www.gnu.org/licenses/>.
3165+#
3166+#***********************************************
3167+
3168+lib: serializer_test
3169+ @./serializer_test
3170+ @cp -v serializer.h ../include
3171+ @cp -v serializer.o ../obj
3172+ @echo build complete
3173+
3174+serializer.o: serializer.h serializer.cpp Makefile
3175+ @rm -f serializer.o
3176+ g++ -c serializer.cpp -I ../include
3177+
3178+serializer_test: serializer.o serializer_test.cpp
3179+ @rm -f serializer_test
3180+ g++ -c serializer_test.cpp -I../include
3181+ g++ -o serializer_test serializer_test.o serializer.o ../obj/base_thread.o -lpthread ../obj/common.o
3182+
3183+clean:
3184+ @rm -rvf *.o serializer_test ../include/serializer.h ../obj/serializer.o
3185+ @echo all objects and executables have been erased.
3186
3187=== added file 'common/serializer/serializer.cpp'
3188--- common/serializer/serializer.cpp 1970-01-01 00:00:00 +0000
3189+++ common/serializer/serializer.cpp 2011-08-25 04:57:16 +0000
3190@@ -0,0 +1,43 @@
3191+/***********************************************
3192+ T his file is part of the NRTB project (https://*launchpad.net/nrtb).
3193+
3194+ NRTB is free software: you can redistribute it and/or modify
3195+ it under the terms of the GNU General Public License as published by
3196+ the Free Software Foundation, either version 3 of the License, or
3197+ (at your option) any later version.
3198+
3199+ NRTB is distributed in the hope that it will be useful,
3200+ but WITHOUT ANY WARRANTY; without even the implied warranty of
3201+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3202+ GNU General Public License for more details.
3203+
3204+ You should have received a copy of the GNU General Public License
3205+ along with NRTB. If not, see <http://www.gnu.org/licenses/>.
3206+
3207+ **********************************************/
3208+
3209+#include "serializer.h"
3210+#include <base_thread.h>
3211+
3212+using namespace nrtb;
3213+
3214+nrtb::serializer::serializer()
3215+{
3216+ counter = 0;
3217+};
3218+
3219+nrtb::serializer::serializer(unsigned long long start)
3220+{
3221+ counter = start;
3222+};
3223+
3224+serializer::~serializer()
3225+{
3226+ // nop destructor
3227+};
3228+
3229+unsigned long long serializer::operator()()
3230+{
3231+ nrtb::scope_lock mylock(lock);
3232+ return counter++;
3233+}
3234
3235=== added file 'common/serializer/serializer.h'
3236--- common/serializer/serializer.h 1970-01-01 00:00:00 +0000
3237+++ common/serializer/serializer.h 2011-08-25 04:57:16 +0000
3238@@ -0,0 +1,50 @@
3239+/***********************************************
3240+ This file is part of the NRTB project (https://*launchpad.net/nrtb).
3241+
3242+ NRTB is free software: you can redistribute it and/or modify
3243+ it under the terms of the GNU General Public License as published by
3244+ the Free Software Foundation, either version 3 of the License, or
3245+ (at your option) any later version.
3246+
3247+ NRTB is distributed in the hope that it will be useful,
3248+ but WITHOUT ANY WARRANTY; without even the implied warranty of
3249+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3250+ GNU General Public License for more details.
3251+
3252+ You should have received a copy of the GNU General Public License
3253+ along with NRTB. If not, see <http://www.gnu.org/licenses/>.
3254+
3255+ **********************************************/
3256+
3257+#ifndef nrtb_serializer_h
3258+#define nrtb_serializer_h
3259+#include <base_thread.h>
3260+
3261+namespace nrtb
3262+{
3263+ /******************************************************************
3264+ * nrtb::serializer provides a simple, thread safe functor which
3265+ * returns a series of long long ints increasing by one each time
3266+ * it's called. By default it starts counting from zero, but may
3267+ * be started from any arbitrary integer in the range
3268+ * 0 < x < max long long.
3269+ * ***************************************************************/
3270+ class serializer
3271+ {
3272+ public:
3273+ // default constructor; counter starts from zero.
3274+ serializer();
3275+ // constructor which sets the starting number.
3276+ serializer(unsigned long long start);
3277+ // NOP distructor for inheritance safety
3278+ ~serializer();
3279+ // functor method, returns the next value in the sequence.
3280+ unsigned long long operator ()();
3281+ private:
3282+ nrtb::mutex lock;
3283+ unsigned long long int counter;
3284+ };
3285+
3286+}
3287+
3288+#endif // nrtb_serializer_h
3289\ No newline at end of file
3290
3291=== added file 'common/serializer/serializer_test.cpp'
3292--- common/serializer/serializer_test.cpp 1970-01-01 00:00:00 +0000
3293+++ common/serializer/serializer_test.cpp 2011-08-25 04:57:16 +0000
3294@@ -0,0 +1,56 @@
3295+/***********************************************
3296+ T his file is part of the NRTB project (https://*launchpad.net/nrtb).
3297+
3298+ NRTB is free software: you can redistribute it and/or modify
3299+ it under the terms of the GNU General Public License as published by
3300+ the Free Software Foundation, either version 3 of the License, or
3301+ (at your option) any later version.
3302+
3303+ NRTB is distributed in the hope that it will be useful,
3304+ but WITHOUT ANY WARRANTY; without even the implied warranty of
3305+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3306+ GNU General Public License for more details.
3307+
3308+ You should have received a copy of the GNU General Public License
3309+ along with NRTB. If not, see <http://www.gnu.org/licenses/>.
3310+
3311+ **********************************************/
3312+
3313+#include "serializer.h"
3314+#include <iostream>
3315+
3316+using namespace nrtb;
3317+using namespace std;
3318+
3319+int main()
3320+{
3321+ cout << "** nrtb::serializer unit test **" << endl;
3322+ bool set_if_failed = false;
3323+ serializer set_default;
3324+ serializer set_start(20);
3325+ serializer rollover((unsigned long long)(0 - 1));
3326+ cout << "Default initialization" << endl;
3327+ cout << " " << set_default();
3328+ cout << " " << set_default();
3329+ cout << " " << set_default();
3330+ cout << endl;
3331+ if (set_default() != 3)
3332+ set_if_failed = true;
3333+ cout << "Started from twenty" << endl;
3334+ cout << " " << set_start();
3335+ cout << " " << set_start();
3336+ cout << " " << set_start();
3337+ cout << endl;
3338+ if (set_start() != 23)
3339+ set_if_failed = true;
3340+ cout << "Rollover Demonstration" << endl;
3341+ cout << " " << rollover();
3342+ cout << " " << rollover();
3343+ cout << " " << rollover();
3344+ cout << endl;
3345+ if (rollover() != 2)
3346+ set_if_failed = true;
3347+ if (set_if_failed)
3348+ cout << "UNIT TEST FAILED" << endl;
3349+ return set_if_failed;
3350+};
3351\ No newline at end of file
3352
3353=== added directory 'common/singleton'
3354=== removed directory 'common/singleton'
3355=== added file 'common/singleton/Makefile'
3356--- common/singleton/Makefile 1970-01-01 00:00:00 +0000
3357+++ common/singleton/Makefile 2011-08-25 04:57:16 +0000
3358@@ -0,0 +1,33 @@
3359+#***********************************************
3360+# This file is part of the NRTB project (https://launchpad.net/nrtb).
3361+#
3362+# NRTB is free software: you can redistribute it and/or modify
3363+# it under the terms of the GNU General Public License as published by
3364+# the Free Software Foundation, either version 3 of the License, or
3365+# (at your option) any later version.
3366+#
3367+# NRTB is distributed in the hope that it will be useful,
3368+# but WITHOUT ANY WARRANTY; without even the implied warranty of
3369+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3370+# GNU General Public License for more details.
3371+#
3372+# You should have received a copy of the GNU General Public License
3373+# along with NRTB. If not, see <http://www.gnu.org/licenses/>.
3374+#
3375+#***********************************************
3376+
3377+
3378+lib: singleton_test
3379+ @./singleton_test
3380+ @cp -v singleton.h ../include
3381+ @echo build complete
3382+
3383+singleton_test: singleton_test.cpp Makefile
3384+ @rm -f singleton_test
3385+ g++ -c singleton_test.cpp -I ../include
3386+ g++ -o singleton_test singleton_test.o ../obj/base_thread.o ../obj/common.o ../obj/serializer.o -lpthread
3387+
3388+clean:
3389+ @rm -rvf *.o singleton_test ../include/singleton.h
3390+ @echo all objects and executables have been erased.
3391+
3392
3393=== removed file 'common/singleton/Makefile'
3394--- common/singleton/Makefile 2010-01-14 02:24:25 +0000
3395+++ common/singleton/Makefile 1970-01-01 00:00:00 +0000
3396@@ -1,18 +0,0 @@
3397-
3398-build: singleton_test
3399- @echo build complete
3400-
3401-singleton_test: singleton_test.cpp Makefile
3402- @rm -f singleton_test
3403- g++ -c singleton_test.cpp -idirafter ../../include3 -idirafter /usr/local/include/boost-1_31
3404-# g++ -c -g singleton_test.cpp -idirafter ../../include3 -idirafter /usr/local/include/boost-1_31
3405- g++ -o singleton_test singleton_test.o -lricklib3 -lpthread -lssl -L../../lib/
3406-
3407-clean:
3408- @rm -rvf *.o singleton_test ../../include3/singleton.h
3409- @echo all objects and executables have been erased.
3410-
3411-lib: ../../include3/singleton.h
3412-
3413-../../include3/singleton.h: singleton.h
3414- @cp -fv singleton.h ../../include3
3415
3416=== added file 'common/singleton/singleton.h'
3417--- common/singleton/singleton.h 1970-01-01 00:00:00 +0000
3418+++ common/singleton/singleton.h 2011-08-25 04:57:16 +0000
3419@@ -0,0 +1,123 @@
3420+/***********************************************
3421+ This file is part of the NRTB project (https://*launchpad.net/nrtb).
3422+
3423+ NRTB is free software: you can redistribute it and/or modify
3424+ it under the terms of the GNU General Public License as published by
3425+ the Free Software Foundation, either version 3 of the License, or
3426+ (at your option) any later version.
3427+
3428+ NRTB is distributed in the hope that it will be useful,
3429+ but WITHOUT ANY WARRANTY; without even the implied warranty of
3430+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3431+ GNU General Public License for more details.
3432+
3433+ You should have received a copy of the GNU General Public License
3434+ along with NRTB. If not, see <http://www.gnu.org/licenses/>.
3435+
3436+ **********************************************/
3437+
3438+/* implements a template that takes any class provided and
3439+ * creates a singleton for it.
3440+ *
3441+ * fps 2002-5-29
3442+ */
3443+
3444+#ifndef nrtb_singleton_h
3445+#define nrtb_singleton_h
3446+
3447+#include <base_thread.h>
3448+
3449+namespace nrtb
3450+{
3451+
3452+/** Wrapper template to create singleton classes.
3453+ **
3454+ ** Classic Singleton pattern template, with thread-safe
3455+ ** methods for getting an instance and destruction.
3456+ **
3457+ ** Singletons are classes that:
3458+ ** (1) Insure that there are no more than one instance of the
3459+ ** class at any time.
3460+ ** (2) Allocate themselves automagically when accessed for the
3461+ ** first time.
3462+ ** (3) Provide a globally available access method to allow any
3463+ ** scope to gain access and use the instance.
3464+ **
3465+ ** This template can create a singleton version of any class that has a
3466+ ** no-argument constructor. The resulting class will have the same
3467+ ** inteface as the object used to create the template with the constructor
3468+ ** and destructor made protected and the addition of the get_instance()
3469+ ** and delete_me() methods.
3470+ **
3471+ ** See the documentation on the get_instance() and delete_me() methods for
3472+ ** usage.
3473+ **/
3474+template <class T, int mytag=0>
3475+class singleton: public T
3476+{
3477+ private:
3478+ static mutex __mylock;
3479+ static singleton * __me;
3480+ protected:
3481+ singleton() : T() {};
3482+ virtual ~singleton() {};
3483+ singleton(const singleton &) {};
3484+ public:
3485+ /** Used to access the object.
3486+ **
3487+ ** Returns a reference to the instanciated singleton object. If
3488+ ** the object has not been accessed before, the object will be
3489+ ** instanciated automatically.
3490+ **
3491+ ** As is usual for the method that provides access to a singleton,
3492+ ** this method is static, allowing it to be called via the class
3493+ ** name as shown. Remember you can only assign the return value to
3494+ ** a reference:
3495+ **
3496+ ** mytype & a = mytype::get_instance();
3497+ **
3498+ ** Attempts to make a copy of the instance should throw a compiler
3499+ ** error.
3500+ **
3501+ ** This method is thread safe, but that does not imply that the
3502+ ** class returned is thread-safe overall; that would depend on the
3503+ ** implementation of the class used to instaciate the template.
3504+ **/
3505+ static singleton & get_instance()
3506+ {
3507+ // First test avoids expensive mutex cycle
3508+ // if the object is already allocated.
3509+ if (!__me)
3510+ {
3511+ scope_lock lock(__mylock);
3512+ // second test required in case multiple threads
3513+ // get past the first check.
3514+ if (!__me)
3515+ {
3516+ __me = new singleton;
3517+ };
3518+ };
3519+ return *__me;
3520+ };
3521+
3522+ /** Destructs and deallocates the singleton object.
3523+ **
3524+ ** After a call to this method, the singleton object will
3525+ ** be destructed and deallocated from memory. However, it
3526+ ** will be automatically reconstruted and allocated if
3527+ ** get_instance() called at any time afterword.
3528+ **/
3529+ void delete_me()
3530+ {
3531+ scope_lock lock(__mylock);
3532+ if (__me) delete __me;
3533+ __me = 0;
3534+ };
3535+};
3536+
3537+template <class T, int mytag> mutex singleton<T,mytag>::__mylock;
3538+template <class T, int mytag> singleton<T,mytag> * singleton<T,mytag>::__me = 0;
3539+
3540+} // namespace nrtb;
3541+
3542+#endif // nrtb_singleton_h
3543
3544=== removed file 'common/singleton/singleton.h'
3545--- common/singleton/singleton.h 2010-01-14 02:24:25 +0000
3546+++ common/singleton/singleton.h 1970-01-01 00:00:00 +0000
3547@@ -1,110 +0,0 @@
3548-/* implements a template that takes any class provided and
3549- * creates a singleton for it.
3550- *
3551- * fps 2002-5-29
3552- */
3553-
3554-/*
3555- TODO: Alter to use boost::threads mutexes.
3556-*/
3557-
3558-
3559-#ifndef NRTB_singleton_h
3560-#define NRTB_singleton_h
3561-
3562-#include <boost/thread>
3563-
3564-namespace NRTB
3565-{
3566-
3567-/** Wrapper template to create singleton classes.
3568- **
3569- ** Classic Singleton pattern template, with thread-safe
3570- ** methods for getting an instance and destruction.
3571- **
3572- ** Singletons are classes that:
3573- ** (1) Insure that there are no more than one instance of the
3574- ** class at any time.
3575- ** (2) Allocate themselves automagically when accessed for the
3576- ** first time.
3577- ** (3) Provide a globally available access method to allow any
3578- ** scope to gain access and use the instance.
3579- **
3580- ** This template can create a singleton version of any class that has a
3581- ** no-argument constructor. The resulting class will have the same
3582- ** inteface as the object used to create the template with the constructor
3583- ** and destructor made protected and the addition of the get_instance()
3584- ** and delete_me() methods.
3585- **
3586- ** See the documentation on the get_instance() and delete_me() methods for
3587- ** usage.
3588- **/
3589-template <class T, int mytag=0>
3590-class singleton: public T
3591-{
3592- private:
3593- static mutex __mylock;
3594- static singleton * __me;
3595- protected:
3596- singleton() : T() {};
3597- virtual ~singleton() {};
3598- singleton(const singleton &) {};
3599- public:
3600- /** Used to access the object.
3601- **
3602- ** Returns a reference to the instanciated singleton object. If
3603- ** the object has not been accessed before, the object will be
3604- ** instanciated automatically.
3605- **
3606- ** As is usual for the method that provides access to a singleton,
3607- ** this method is static, allowing it to be called via the class
3608- ** name as shown. Remember you can only assign the return value to
3609- ** a reference:
3610- **
3611- ** mytype & a = mytype::get_instance();
3612- **
3613- ** Attempts to make a copy of the instance should throw a compiler
3614- ** error.
3615- **
3616- ** This method is thread safe, but that does not imply that the
3617- ** class returned is thread-safe overall; that would depend on the
3618- ** implementation of the class used to instaciate the template.
3619- **/
3620- static singleton & get_instance()
3621- {
3622- // First test avoids expensive mutex cycle
3623- // if the object is already allocated.
3624- if (!__me)
3625- {
3626- scope_lock lock(__mylock);
3627- // second test required in case multiple threads
3628- // get past the first check.
3629- if (!__me)
3630- {
3631- __me = new singleton;
3632- };
3633- };
3634- return *__me;
3635- };
3636-
3637- /** Destructs and deallocates the singleton object.
3638- **
3639- ** After a call to this method, the singleton object will
3640- ** be destructed and deallocated from memory. However, it
3641- ** will be automatically reconstruted and allocated if
3642- ** get_instance() called at any time afterword.
3643- **/
3644- void delete_me()
3645- {
3646- scope_lock lock(__mylock);
3647- if (__me) delete __me;
3648- __me = 0;
3649- };
3650-};
3651-
3652-template <class T, int mytag> mutex singleton<T,mytag>::__mylock;
3653-template <class T, int mytag> singleton<T,mytag> * singleton<T,mytag>::__me = 0;
3654-
3655-} // namespace NRTB;
3656-
3657-#endif // NRTB_singleton_h
3658
3659=== added file 'common/singleton/singleton_test.cpp'
3660--- common/singleton/singleton_test.cpp 1970-01-01 00:00:00 +0000
3661+++ common/singleton/singleton_test.cpp 2011-08-25 04:57:16 +0000
3662@@ -0,0 +1,55 @@
3663+/***********************************************
3664+ This file is part of the NRTB project (https://*launchpad.net/nrtb).
3665+
3666+ NRTB is free software: you can redistribute it and/or modify
3667+ it under the terms of the GNU General Public License as published by
3668+ the Free Software Foundation, either version 3 of the License, or
3669+ (at your option) any later version.
3670+
3671+ NRTB is distributed in the hope that it will be useful,
3672+ but WITHOUT ANY WARRANTY; without even the implied warranty of
3673+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3674+ GNU General Public License for more details.
3675+
3676+ You should have received a copy of the GNU General Public License
3677+ along with NRTB. If not, see <http://www.gnu.org/licenses/>.
3678+
3679+ **********************************************/
3680+
3681+// singleton template test program
3682+
3683+#include "singleton.h"
3684+#include <serializer.h>
3685+#include <iostream>
3686+
3687+using namespace nrtb;
3688+using namespace std;
3689+
3690+typedef singleton<serializer> sequence_type;
3691+
3692+int main()
3693+{
3694+
3695+ cout << "============== singleton unit test ================"
3696+ << endl;
3697+ int er_count = 0;
3698+
3699+ sequence_type & a = sequence_type::get_instance();
3700+
3701+ for (int i=0; i<10; i++)
3702+ {
3703+ cout << a();
3704+ };
3705+
3706+ sequence_type & b = sequence_type::get_instance();
3707+
3708+ if ( b() != 10)
3709+ {
3710+ er_count++;
3711+ };
3712+
3713+ cout << "\n=========== singleton test " << (er_count ? "failed" : "passed")
3714+ << " =============" << endl;
3715+
3716+ return er_count;
3717+};
3718
3719=== removed file 'common/singleton/singleton_test.cpp'
3720--- common/singleton/singleton_test.cpp 2010-01-14 02:24:25 +0000
3721+++ common/singleton/singleton_test.cpp 1970-01-01 00:00:00 +0000
3722@@ -1,32 +0,0 @@
3723-// singleton template test program
3724-
3725-
3726-#include <http_page.h>
3727-#include "singleton.h"
3728-#include <iostream>
3729-
3730-using namespace NRTB;
3731-using namespace std;
3732-
3733-int main()
3734-{
3735- typedef singleton<http_page> p_type;
3736-
3737- {
3738- p_type & getter = p_type::get_instance();
3739-
3740- cout << "newly initialized code: " << getter.result_code() << endl;
3741-
3742- getter.get("127.0.0.1:80","/");
3743- };
3744-
3745- cout << "first response code: " << p_type::get_instance().result_code()
3746- << endl;
3747-
3748- p_type::get_instance().get("127.0.0.1:80","/not_there.html");
3749-
3750- cout << "second response code: " << p_type::get_instance().result_code()
3751- << endl;
3752-
3753- p_type::get_instance().delete_me();
3754-};
3755
3756=== added directory 'common/sockets'
3757=== added file 'common/sockets/Makefile'
3758--- common/sockets/Makefile 1970-01-01 00:00:00 +0000
3759+++ common/sockets/Makefile 2011-08-25 04:57:16 +0000
3760@@ -0,0 +1,38 @@
3761+#***********************************************
3762+# This file is part of the NRTB project (https://launchpad.net/nrtb).
3763+#
3764+# NRTB is free software: you can redistribute it and/or modify
3765+# it under the terms of the GNU General Public License as published by
3766+# the Free Software Foundation, either version 3 of the License, or
3767+# (at your option) any later version.
3768+#
3769+# NRTB is distributed in the hope that it will be useful,
3770+# but WITHOUT ANY WARRANTY; without even the implied warranty of
3771+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3772+# GNU General Public License for more details.
3773+#
3774+# You should have received a copy of the GNU General Public License
3775+# along with NRTB. If not, see <http://www.gnu.org/licenses/>.
3776+#
3777+#***********************************************
3778+
3779+lib: socket_test
3780+ @./socket_test
3781+ @cp -v base_socket.h ../include/
3782+ @cp -v base_socket.o ../obj/
3783+ @echo build complete
3784+
3785+socket_test: base_socket.o socket_test.cpp
3786+ @rm -f socket_test
3787+ g++ -c socket_test.cpp -I ../include
3788+ g++ -o socket_test socket_test.o base_socket.o ../obj/hires_timer.o ../obj/common.o ../obj/base_thread.o -lpthread
3789+
3790+
3791+base_socket.o: base_socket.cpp base_socket.h Makefile
3792+ @rm -f base_socket.o
3793+ g++ -c -O3 base_socket.cpp -I ../include
3794+
3795+clean:
3796+ @rm -vf *.o ../include/base_socket.h socket_test
3797+ @echo all objects and executables have been erased.
3798+
3799
3800=== added file 'common/sockets/base_socket.cpp'
3801--- common/sockets/base_socket.cpp 1970-01-01 00:00:00 +0000
3802+++ common/sockets/base_socket.cpp 2011-08-25 04:57:16 +0000
3803@@ -0,0 +1,853 @@
3804+/***********************************************
3805+ This file is part of the NRTB project (https://*launchpad.net/nrtb).
3806+
3807+ NRTB is free software: you can redistribute it and/or modify
3808+ it under the terms of the GNU General Public License as published by
3809+ the Free Software Foundation, either version 3 of the License, or
3810+ (at your option) any later version.
3811+
3812+ NRTB is distributed in the hope that it will be useful,
3813+ but WITHOUT ANY WARRANTY; without even the implied warranty of
3814+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3815+ GNU General Public License for more details.
3816+
3817+ You should have received a copy of the GNU General Public License
3818+ along with NRTB. If not, see <http://www.gnu.org/licenses/>.
3819+
3820+ **********************************************/
3821+
3822+// see base_socket.h for documentation
3823+
3824+#include "base_socket.h"
3825+#include <string.h>
3826+#include <errno.h>
3827+#include <arpa/inet.h>
3828+#include <netdb.h>
3829+#include <boost/lexical_cast.hpp>
3830+
3831+using boost::lexical_cast;
3832+using std::string;
3833+
3834+namespace nrtb
3835+{
3836+
3837+// added for Solaris 2.6
3838+#ifdef no_inet_aton
3839+int inet_aton(const char * addr, in_addr * inp)
3840+{
3841+ // this workaround defines inet_aton in term in_addr. Drawbacks are
3842+ // that there is no useful error checking.
3843+ inp->s_addr = inet_addr(addr);
3844+ return (inp->s_addr != 0);
3845+};
3846+#endif // no_inet_aton
3847+
3848+// added for solaris 2.6
3849+#ifdef no_socklen_t
3850+typedef int socklen_t;
3851+#endif // no_sock_len_t
3852+
3853+int tcp_socket::transmit(const string & data)
3854+{
3855+ return send(mysock,data.c_str(),data.length(),MSG_DONTWAIT);
3856+};
3857+
3858+int tcp_socket::receive(std::string & data, int limit)
3859+{
3860+ errno = 0;
3861+ data = "";
3862+ // make more room in the input buffer if needed.
3863+ int bufsize = limit + 1;
3864+ if (bufsize > inbuff.size()) inbuff.resize(bufsize);
3865+ // get the data to inbuff
3866+ int returnme = recv(mysock,(void *) &(inbuff[0]),limit,0);
3867+ // did we get anything?
3868+ if (returnme > 0)
3869+ {
3870+ // yes.. store for the caller.
3871+ data.resize(returnme,0);
3872+ for (int i=0; i<returnme; i++)
3873+ {
3874+ data[i] = inbuff[i];
3875+ };
3876+ }
3877+ // ... or was there an error?
3878+ else if (errno)
3879+ {
3880+ // flag it for the caller.
3881+ returnme = -1;
3882+ };
3883+ return returnme;
3884+};
3885+
3886+tcp_socket::tcp_socket(bool autoclose)
3887+{
3888+ close_on_destruct = autoclose;
3889+ mysock = socket(AF_INET,SOCK_STREAM,0);
3890+ _status = sock_init;
3891+ _last_error = 0;
3892+};
3893+
3894+tcp_socket::tcp_socket(int existing_socket, bool autoclose)
3895+{
3896+ close_on_destruct = autoclose;
3897+ mysock = existing_socket;
3898+ _status = sock_connect;
3899+ _last_error = 0;
3900+};
3901+
3902+tcp_socket::~tcp_socket()
3903+{
3904+ if (close_on_destruct)
3905+ {
3906+ shutdown(mysock,SHUT_RDWR);
3907+ ::close(mysock);
3908+ _status = sock_undef;
3909+ };
3910+};
3911+
3912+void tcp_socket::reset()
3913+{
3914+ // close the old socket if we can.
3915+ try { close(); } catch (tcp_socket::general_exception) {};
3916+ // get a new one.
3917+ mysock = socket(AF_INET,SOCK_STREAM,0);
3918+ // set up the default conditions;
3919+ _status = sock_init;
3920+ _last_error = 0;
3921+};
3922+
3923+sockaddr_in tcp_socket::str_to_sockaddr(const string & address)
3924+{
3925+ sockaddr_in in_address;
3926+ // init our address structure.
3927+ memset(&in_address,0,sizeof(in_address));
3928+ //in_address.sin_len = 16;
3929+ in_address.sin_family = AF_INET;
3930+ // seperate the IP and port addresses.
3931+ const int IP = 0;
3932+ const int PORT = 1;
3933+ strlist addr;
3934+ addr = split(address,':');
3935+ if (addr.size() != 2)
3936+ {
3937+ throw bad_address_exception();
3938+ };
3939+ if (addr[IP] != "*")
3940+ {
3941+ // first attempt name resolution
3942+ hostent * name = gethostbyname(addr[IP].c_str());
3943+ if ((name != 0) && (name->h_length > 0))
3944+ {
3945+ in_address.sin_addr = *( (in_addr *) (name->h_addr_list[0]));
3946+ }
3947+ else if (!inet_aton(addr[IP].c_str(),&in_address.sin_addr))
3948+ {
3949+ throw bad_address_exception();
3950+ };
3951+ };
3952+ if (addr[PORT] != "*")
3953+ {
3954+ // get the good port;
3955+ uint16_t port = lexical_cast<uint16_t>(addr[PORT]);
3956+ in_address.sin_port = htons(port);
3957+ };
3958+ return in_address;
3959+};
3960+
3961+string tcp_socket::sockaddr_to_str(const sockaddr_in & address)
3962+{
3963+ // get the IP address.
3964+ string returnme = inet_ntoa(address.sin_addr);
3965+ // adjust for wild card if appropriate.
3966+ if (returnme == "0.0.0.0") { returnme = "*"; };
3967+ // get the port address
3968+ returnme += ":";
3969+ uint16_t myport = ntohs(address.sin_port);
3970+ if (myport > 0 )
3971+ {
3972+ returnme += lexical_cast<string>(myport);
3973+ }
3974+ else
3975+ {
3976+ returnme += "*";
3977+ };
3978+ return returnme;
3979+};
3980+
3981+void tcp_socket::bind(const string & address)
3982+{
3983+ if (address != "*:*")
3984+ {
3985+ sockaddr_in in_address = str_to_sockaddr(address);
3986+ socklen_t socklen = sizeof(in_address);
3987+ // try bind.
3988+ if (::bind(mysock, (sockaddr*) &in_address, socklen))
3989+ {
3990+ // failed in some way.
3991+ _last_error = errno;
3992+ cant_bind_exception e;
3993+ e.store(address);
3994+ throw e;
3995+ };
3996+ }; // nop if "*:*" is passed in.
3997+};
3998+
3999+void tcp_socket::connect(const string & address, int timeout)
4000+{
4001+ sockaddr_in in_address = str_to_sockaddr(address);
4002+ if (::connect(mysock, ( sockaddr *) &in_address, sizeof(in_address)))
4003+ {
4004+ _last_error = errno;
4005+ bad_connect_exception e;
4006+ e.store(address);
4007+ throw e;
4008+ }
4009+ else
4010+ {
4011+ _status = sock_connect;
4012+ };
4013+};
4014+
4015+void tcp_socket::close()
4016+{
4017+ if (::close(mysock))
4018+ {
4019+ _last_error = errno;
4020+ throw close_exception();
4021+ }
4022+ else
4023+ {
4024+ _status = sock_close;
4025+ };
4026+};
4027+
4028+int tcp_socket::put(string s, int timeout)
4029+{
4030+ // set up for the testing loop.
4031+ time_t endtime = time(NULL);
4032+ int orig_len = s.length();
4033+ endtime += timeout;
4034+ // Try to send.
4035+ bool done = false;
4036+ while (!done)
4037+ {
4038+ // make an attempt.
4039+ int results = transmit(s);
4040+ // remove the chars already sent from the buffer and set done
4041+ // if appropriate.
4042+ if (results > 0)
4043+ {
4044+ s.erase(0,results);
4045+ done = (s.length() == 0) ? true : false;
4046+ };
4047+ // decide what do do about any possible error results.
4048+ if (results == -1)
4049+ {
4050+ switch (errno)
4051+ {
4052+ case EBADF :
4053+ case ENOTSOCK:
4054+ {
4055+ done = true;
4056+ _last_error = errno;
4057+ _status = sock_close;
4058+ not_open_exception e;
4059+ e.store(s);
4060+ throw e;
4061+ break;
4062+ };
4063+ case ENOBUFS :
4064+ case ENOMEM :
4065+ {
4066+ done = true;
4067+ _last_error = errno;
4068+ buffer_full_exception e;
4069+ e.store(s);
4070+ throw e;
4071+ break;
4072+ };
4073+ case EINTR:
4074+ case EAGAIN :
4075+// case EWOULDBLOCK :
4076+ {
4077+ usleep(50);
4078+ break;
4079+ };
4080+ default :
4081+ {
4082+ done = true;
4083+ _last_error = errno;
4084+ general_exception e;
4085+ e.store(s);
4086+ throw e;
4087+ break;
4088+ };
4089+ }; // switch (errno)
4090+ }; // until error,
4091+ if ((timeout > 0) && ((time(NULL) >= endtime)))
4092+ {
4093+ done = true;
4094+ };
4095+ }; // continue sending until success or error or timeout.
4096+ // check for timeout.
4097+ int sent = orig_len - s.length();
4098+ if (sent != orig_len)
4099+ {
4100+ timeout_exception e;
4101+ e.store(s);
4102+ throw e;
4103+ };
4104+ return sent;
4105+};
4106+
4107+string tcp_socket::get(int maxlen, int timeout)
4108+{
4109+/*
4110+micro_timer run_time;
4111+run_time.start();
4112+std::cerr << "ENTER get(" << maxlen << "," << timeout << ")" << std::endl;
4113+*/
4114+ string returnme = "";
4115+ returnme.reserve(maxlen);
4116+ string in_buffer;
4117+ // set out timeout marker.
4118+ time_t endtime = time(NULL);
4119+ endtime += timeout;
4120+ timeval wait;
4121+ // input loop
4122+ bool done = false;
4123+ while (!done)
4124+ {
4125+ time_t waittime = endtime - time(NULL);
4126+ wait.tv_sec = (waittime > 0) ? waittime : 0;
4127+ wait.tv_usec = 10;
4128+ // set max timeout.
4129+ // the assert is used because some platforms may not properly support
4130+ // the SO_RCVTIMEO socket option.
4131+ setsockopt(mysock,SOL_SOCKET,SO_RCVTIMEO,&wait,sizeof(wait));
4132+ // is there any data waiting?
4133+ int results = receive(in_buffer,maxlen-returnme.size());
4134+ // was there an error?
4135+ switch (results)
4136+ {
4137+ case 0:
4138+ {
4139+ if (returnme == "")
4140+ {
4141+ throw not_open_exception();
4142+ }
4143+ else
4144+ {
4145+ done = true;
4146+ }
4147+ break;
4148+ }
4149+ case -1 :
4150+ {
4151+ switch (errno)
4152+ {
4153+ case EBADF :
4154+ case ENOTCONN :
4155+ case ENOTSOCK :
4156+ {
4157+ done = true;
4158+ _last_error = errno;
4159+ _status = sock_close;
4160+ if (returnme == "")
4161+ {
4162+ not_open_exception e;
4163+ e.store(returnme);
4164+ throw e;
4165+ };
4166+ break;
4167+ }
4168+ case EAGAIN : // shouldn't happen, but .....
4169+ case EINTR : // this too....
4170+ {
4171+ if (timeout == 0)
4172+ {
4173+ done = true;
4174+ };
4175+ usleep(50);
4176+ break;
4177+ }
4178+ default :
4179+ {
4180+ done = true;
4181+ _last_error = errno;
4182+ if (returnme == "")
4183+ {
4184+ general_exception e;
4185+ e.store(returnme);
4186+ throw e;
4187+ };
4188+ break;
4189+ }
4190+ }; // there was an error.
4191+ break;
4192+ }
4193+ default:
4194+ {
4195+ returnme += in_buffer;
4196+ break;
4197+ }
4198+ };
4199+ // check boundry conditions;
4200+ // -- maxlen only effective if maxlen > 0.
4201+ if ((maxlen > 0) && (returnme.length() >= maxlen)) { done = true; };
4202+ // -- timeout only effective if timeout > 0.
4203+ if ((timeout > 0) && (time(NULL) > endtime)) { done = true; };
4204+ if (timeout == 0) { done = true; };
4205+/*
4206+std::cerr << "\tstatus: " << returnme.size()
4207+<< ", done = " << done
4208+<< " (" << run_time.interval() << ")"
4209+<< std::endl;
4210+*/
4211+ }; // input loop.
4212+ // did we time out?
4213+ if ((timeout > 0) && (time(NULL) > endtime))
4214+ {
4215+ timeout_exception e;
4216+ e.store(returnme);
4217+ throw e;
4218+ };
4219+ // done!
4220+ return returnme;
4221+};
4222+
4223+
4224+string tcp_socket::getln(string eol, int maxlen, int timeout)
4225+{
4226+ // args check.
4227+ if (eol == "")
4228+ {
4229+ throw bad_args_exception();
4230+ return eol;
4231+ };
4232+ // setup.
4233+ string returnme = "";
4234+ returnme.reserve(maxlen);
4235+ int targetlen = eol.length();
4236+ int searchlen = targetlen - 1;
4237+ time_t endtime = time(NULL);
4238+ endtime += timeout;
4239+ bool done = false;
4240+ bool success = false;
4241+ // first, get at least as many characters as are in the eol string.
4242+ try
4243+ {
4244+ int wait_time = timeout;
4245+ if (timeout < 0) { wait_time = 0; };
4246+ returnme = get(targetlen,wait_time);
4247+ }
4248+ catch (timeout_exception e)
4249+ {
4250+ // if get timed out we may be done.
4251+ if (timeout >= 0) { done = true; };
4252+ returnme = e.comment();
4253+ };
4254+ // We only need to continue if we have not gotten our token yet.
4255+ if ((!done) && (returnme.length() >= targetlen))
4256+ {
4257+// success = returnme.substr(returnme.length()-targetlen,targetlen) == eol;
4258+ success = returnme.find(eol,returnme.length()-targetlen) != string::npos;
4259+ };
4260+ while (!done && !success)
4261+ {
4262+ // still more to get, if we have time.
4263+ int timeleft = endtime - time(NULL);
4264+ timeleft = (timeleft > 0) ? timeleft : 0;
4265+ // can we increase our get length?
4266+ int getlen = 1;
4267+ if (searchlen > 1)
4268+ {
4269+ // see if a token start is near.
4270+ if (returnme.find(eol[0],returnme.length()-searchlen) == string::npos)
4271+ {
4272+ // great!.. get just less than one token's worth.
4273+ getlen = searchlen;
4274+ }
4275+ };
4276+ // okay.. let's get the next chunk
4277+ try
4278+ {
4279+ returnme += get(getlen,timeleft);
4280+ }
4281+ catch (timeout_exception e)
4282+ {
4283+ if (timeout >= 0) { done = true; };
4284+ };
4285+ // check boundary conditions.
4286+ // -- did we get it?
4287+ if (returnme.length() >= targetlen)
4288+ {
4289+// success = returnme.substr(returnme.length()-targetlen,targetlen) == eol;
4290+ success = returnme.find(eol,returnme.length()-targetlen) != string::npos;
4291+ };
4292+ // -- maxlen only effective if maxlen > 0.
4293+ if ((maxlen > 0) && (returnme.length() >= maxlen)) { done = true; };
4294+ };
4295+ // did we error out?
4296+ if (!success)
4297+ {
4298+ // what type of error was it?
4299+ if ((maxlen > 0) && (returnme.length() >= maxlen))
4300+ {
4301+ overrun_exception e;
4302+ e.store(returnme);
4303+ throw e;
4304+ }
4305+ else
4306+ {
4307+ timeout_exception e;
4308+ e.store(returnme);
4309+ throw e;
4310+ };
4311+ };
4312+ return returnme;
4313+};
4314+
4315+string tcp_socket::get_local_address()
4316+{
4317+ sockaddr_in myaddr;
4318+ socklen_t len = sizeof(myaddr);
4319+ int results = getsockname(mysock,(sockaddr *) &myaddr,&len);
4320+ // check that getsockname was okay.
4321+ if (results == -1)
4322+ {
4323+ // some type of error occurred.
4324+ switch (errno)
4325+ {
4326+ case ENOBUFS :
4327+ {
4328+ throw buffer_full_exception();
4329+ break;
4330+ };
4331+ default :
4332+ {
4333+ throw general_exception();
4334+ break;
4335+ };
4336+ }; // switch errno
4337+ }
4338+ return sockaddr_to_str(myaddr);
4339+};
4340+
4341+string tcp_socket::get_remote_address()
4342+{
4343+ sockaddr_in myaddr;
4344+ socklen_t len = sizeof(myaddr);
4345+ int results = getpeername(mysock,(sockaddr *) &myaddr,&len);
4346+ // check that getsockname was okay.
4347+ if (results == -1)
4348+ {
4349+ // some type of error occurred.
4350+ switch (errno)
4351+ {
4352+ case ENOTCONN :
4353+ {
4354+ _status = sock_close;
4355+ throw not_open_exception();
4356+ break;
4357+ };
4358+ case ENOBUFS :
4359+ {
4360+ throw buffer_full_exception();
4361+ break;
4362+ };
4363+ default :
4364+ {
4365+ throw general_exception();
4366+ break;
4367+ };
4368+ }; // switch errno
4369+ }
4370+ return sockaddr_to_str(myaddr);
4371+};
4372+
4373+
4374+tcp_server_socket_factory::tcp_server_socket_factory(
4375+ const string & address, const unsigned short int & backlog)
4376+{
4377+ // does not attempt to set up the connection initially.
4378+ _address = address;
4379+ _backlog = backlog;
4380+ _last_thread_fault = 0;
4381+ thread_return = 0;
4382+ in_on_accept = false;
4383+ connect_sock = 0;
4384+};
4385+
4386+tcp_server_socket_factory::~tcp_server_socket_factory()
4387+{
4388+ // are we current handling requests?
4389+ if (is_running())
4390+ {
4391+ // yes, this is -rude- shutdown of the listening thread.
4392+ // Get over it.
4393+ stop();
4394+ try
4395+ {
4396+ if (listen_sock)
4397+ close(listen_sock);
4398+ }
4399+ catch (...) {};
4400+ };
4401+};
4402+
4403+void tcp_server_socket_factory::start_listen()
4404+{
4405+ // take no action if the listen thread is already running.
4406+ if (!is_running())
4407+ {
4408+ // load up the control flags
4409+ in_on_accept = false;
4410+ okay_to_continue = true;
4411+ thread_return = 0;
4412+ // start it up!
4413+ detach();
4414+ start();
4415+ };
4416+};
4417+
4418+void tcp_server_socket_factory::stop_listen()
4419+{
4420+ // take action only if the listen thread is running.
4421+ if (is_running())
4422+ {
4423+ bool okay_to_kill = false;
4424+ // set the flag that indicates the thread should not process any more.
4425+ {
4426+ scope_lock lock(thread_data);
4427+ bool okay_to_kill = !in_on_accept;
4428+ }
4429+ // close the listener socket.
4430+ close(listen_sock);
4431+ // is is okay to cancel the thread?
4432+ if (!okay_to_kill)
4433+ {
4434+ // we'll allow up to 30 seconds for on_accept() to finish.
4435+ time_t endtime = time(NULL);
4436+ endtime += 30;
4437+ bool done = false;
4438+ while (!done)
4439+ {
4440+ // wait a second...
4441+ sleep(1);
4442+ // check boundaries.
4443+ // -- are we out of on_accept()?
4444+ {
4445+ scope_lock lock(thread_data);
4446+ done = !in_on_accept;
4447+ }
4448+ // -- are we out of time?
4449+ okay_to_kill = done;
4450+ if (time(NULL) > endtime) { done = true; };
4451+ };
4452+ };
4453+ // kill the listener thread.
4454+ if (!okay_to_kill) { throw on_accept_bound_exception(); };
4455+ stop();
4456+ };
4457+};
4458+
4459+bool tcp_server_socket_factory::listening()
4460+{
4461+ bool running = is_running();
4462+ if (!running)
4463+ {
4464+ // check to be sure the thread did not die due to an error.
4465+ if (thread_return != 0)
4466+ {
4467+ // Clear the error state before throwing an exception.
4468+ _last_thread_fault = thread_return;
4469+ thread_return = 0;
4470+ // if thread_return was non-zero, it is assumed the thread died an
4471+ // evil and useless death. Scream in anger!
4472+ throw listen_terminated_exception();
4473+ };
4474+ };
4475+ return running;
4476+};
4477+
4478+unsigned short int tcp_server_socket_factory::backlog()
4479+{
4480+ return _backlog;
4481+};
4482+
4483+void tcp_server_socket_factory::run()
4484+{
4485+ /* Put this entire thing in a try block to protect the application.
4486+ * Without this, an untrapped exception thrown here or in the user supplied
4487+ * on_accept() method would abort the entire application instead of just this
4488+ * thread.
4489+ */
4490+ try
4491+ {
4492+ bool go = true;
4493+ // set up our listening socket.
4494+ listen_sock = socket(AF_INET,SOCK_STREAM,0);
4495+ sockaddr_in myaddr;
4496+ try
4497+ {
4498+ myaddr = tcp_socket::str_to_sockaddr(_address);
4499+ }
4500+ catch (...)
4501+ {
4502+ // probably a tcp_socket::bad_address_exception,
4503+ // but any reason will do.
4504+ go = false;
4505+ };
4506+ if (bind(listen_sock,(sockaddr *) &myaddr,sizeof(myaddr)))
4507+ {
4508+ // bind did not work.
4509+ go = false;
4510+ };
4511+ if (listen(listen_sock,_backlog))
4512+ {
4513+ // listen failed in some way.. I don't care which.
4514+ go = false;
4515+ };
4516+ // processing loop
4517+ while (go)
4518+ {
4519+ // are we okay to proceed?
4520+ {
4521+ scope_lock lock(thread_data);
4522+ in_on_accept = false;
4523+ go = okay_to_continue;
4524+ }
4525+ if (!go)
4526+ {
4527+ close(listen_sock);
4528+ exit(0);
4529+ };
4530+ // accept a new connection
4531+ bool good_connect = true;
4532+ int new_conn = accept(listen_sock,NULL,NULL);
4533+ // validate the accept return value.
4534+ if (new_conn == -1)
4535+ {
4536+ // accept returned an error.
4537+ switch (errno)
4538+ {
4539+ case ENETDOWN :
4540+ case EPROTO :
4541+ case ENOPROTOOPT :
4542+ case EHOSTDOWN :
4543+ case ENONET :
4544+ case EHOSTUNREACH :
4545+ case EOPNOTSUPP :
4546+ case ENETUNREACH :
4547+ case EAGAIN :
4548+// case EWOULDBLOCK :
4549+ case EPERM :
4550+ case ECONNABORTED :
4551+ {
4552+ good_connect = false;
4553+ break;
4554+ };
4555+ default :
4556+ {
4557+ // for any other error, we're going to shutdown the
4558+ // this listener thread.
4559+ {
4560+ scope_lock lock(thread_data);
4561+ // If the error was caused by an attempt to close the
4562+ // socket and shutdown the thread, don't store an
4563+ // error flag.
4564+ if (okay_to_continue)
4565+ {
4566+ thread_return = errno;
4567+ }
4568+ else
4569+ {
4570+ thread_return = 0;
4571+ };
4572+ };
4573+ exit(errno);
4574+ break;
4575+ };
4576+ }; // switch (errno)
4577+ }; // error thrown by accept.
4578+ // create connect_sock
4579+ connect_sock = new tcp_socket(new_conn);
4580+ // are we okay to proceed?
4581+ {
4582+ scope_lock lock(thread_data);
4583+ go = okay_to_continue;
4584+ // if we are go, then we'll be going to on_accept next.
4585+ // Therefore, this equality makes sense if you hold your
4586+ // head just so. :-P
4587+ in_on_accept = go;
4588+ }
4589+ if (!go)
4590+ {
4591+ delete connect_sock;
4592+ close(listen_sock);
4593+ exit(0);
4594+ };
4595+ // only call on_accept() if we have a good connection.
4596+ if (good_connect)
4597+ {
4598+ // make the thread easily cancelable.
4599+ set_cancel_anytime();
4600+ // call on_accept
4601+ on_accept();
4602+ // set back to cancel_deferred.
4603+ set_deferred_cancel();
4604+ };
4605+ }; // while go;
4606+ // if we get here then things are not going well...
4607+ {
4608+ scope_lock lock(thread_data);
4609+ thread_return = -2;
4610+ }
4611+ close(listen_sock);
4612+ exit(-2);
4613+ }
4614+ catch (...)
4615+ {
4616+ /* an untrapped exception was thrown by someone in this thread.
4617+ * We'll shutdown this thread and put -1 in the thread_return field
4618+ * to let the world know that we don't know what killed us.
4619+ */
4620+ thread_data.lock();
4621+ thread_return = -1;
4622+ thread_data.unlock();
4623+ close(listen_sock);
4624+ exit(-1);
4625+ };
4626+};
4627+
4628+} // namespace nrtb
4629+
4630+
4631+
4632+
4633+
4634+
4635+
4636+
4637+
4638+
4639+
4640+
4641+
4642+
4643+
4644+
4645+
4646+
4647+
4648+
4649+
4650+
4651+
4652+
4653+
4654+
4655+
4656+
4657
4658=== added file 'common/sockets/base_socket.h'
4659--- common/sockets/base_socket.h 1970-01-01 00:00:00 +0000
4660+++ common/sockets/base_socket.h 2011-08-25 04:57:16 +0000
4661@@ -0,0 +1,588 @@
4662+/***********************************************
4663+ This file is part of the NRTB project (https://*launchpad.net/nrtb).
4664+
4665+ NRTB is free software: you can redistribute it and/or modify
4666+ it under the terms of the GNU General Public License as published by
4667+ the Free Software Foundation, either version 3 of the License, or
4668+ (at your option) any later version.
4669+
4670+ NRTB is distributed in the hope that it will be useful,
4671+ but WITHOUT ANY WARRANTY; without even the implied warranty of
4672+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4673+ GNU General Public License for more details.
4674+
4675+ You should have received a copy of the GNU General Public License
4676+ along with NRTB. If not, see <http://www.gnu.org/licenses/>.
4677+
4678+ **********************************************/
4679+
4680+#ifndef base_socket_header
4681+#define base_socket_header
4682+
4683+#include <base_thread.h>
4684+#include <boost/shared_ptr.hpp>
4685+#include <sys/socket.h>
4686+#include <netinet/in.h>
4687+
4688+namespace nrtb
4689+{
4690+
4691+/** Provides an easy to use TCP/IP bidirectional communciations socket.
4692+ **
4693+ ** tcp_socket contains all the functionality you'll need for 98% of
4694+ ** your normal, non-encrypted networking communications needs. Everything
4695+ ** from creating the socket, binding it if needed, name resolution,
4696+ ** connecting, sending and receiving, etc. is handled here.
4697+ **
4698+ ** Unless you override it, a tcp_socket closes automatically when it
4699+ ** goes out of scope, preventing hanging sockets.
4700+ **/
4701+class tcp_socket
4702+{
4703+ public:
4704+
4705+ typedef enum {sock_undef,sock_init,sock_connect,sock_close} state;
4706+
4707+ protected:
4708+
4709+ int mysock;
4710+ bool close_on_destruct;
4711+ state _status;
4712+ int _last_error;
4713+ std::vector<unsigned char> inbuff;
4714+
4715+ virtual int transmit(const std::string & data);
4716+ virtual int receive(std::string & data,int limit);
4717+
4718+ public:
4719+
4720+ /// Use to catch all socket exceptions.
4721+ class general_exception: public base_exception {};
4722+ /// Thrown by send or get* if the socket is not open for use.
4723+ class not_open_exception: public general_exception {};
4724+ /// Thrown by get* if more than maxlen chars are receieved.
4725+ class overrun_exception: public general_exception {};
4726+ /// Thrown if a timeout occured during an operation.
4727+ class timeout_exception: public general_exception {};
4728+ /// Thrown if the socket could not connect to the target.
4729+ class bad_connect_exception: public general_exception {};
4730+ /// Thrown if the address argument is not interpretable.
4731+ class bad_address_exception: public general_exception {};
4732+ /// Thrown by bind() if the address/port is not bindable.
4733+ class cant_bind_exception: public general_exception {};
4734+ /// Thrown by close() if an error is reported.
4735+ class close_exception: public general_exception {};
4736+ /// Thrown by send if the message is too large.
4737+ class msg_too_large_exception: public general_exception {};
4738+ /// Thrown by send if buffer overflows.
4739+ class buffer_full_exception: public general_exception {};
4740+ /// Thrown if the socket lib complains of bad args.
4741+ class bad_args_exception: public general_exception {};
4742+
4743+ /** Constructs a tcp_socket.
4744+ **
4745+ ** Prepares this socket for use. If autoclose=true the socket will be
4746+ ** closed when the object is distructed, otherwise it will be left in
4747+ ** whatever state it happened to be in at the time.
4748+ **
4749+ ** BTW, I _don't_ recommend you leave the socket open. If the tcp_socket
4750+ ** was instanciated via this constructor, there will not be any other
4751+ ** references to the socket save the one held privately, so a socket left
4752+ ** open will be there forever. This will almost certainly warrent an
4753+ ** unpleasent visit by one or more SAs of the box(es) hosting your
4754+ ** application over time.
4755+ **
4756+ ** autoclose=true; it's the only way to be sure. ;)
4757+ **/
4758+ tcp_socket(bool autoclose=true);
4759+
4760+ /** Constructs from an already existing socket.
4761+ **
4762+ ** Constructs the tcp_socket from an already existing socket. This
4763+ ** constructor is specifically for use with the traditional listen()
4764+ ** sockets function, and probably should not be used in other contexts.
4765+ **
4766+ ** If autoclose is true the socket will be closed on destruction of the
4767+ ** object, otherwise the socket will be left in whatever state it happened
4768+ ** to be in at the time. As a general rule I suspect you'll want leave
4769+ ** autoclose defaulted to true.
4770+ **
4771+ ** In most cases where you would use listen(), take a look at the
4772+ ** tcp_server_socket_factory class; it'll probably do everything you need
4773+ ** with a minimum of programming overhead.
4774+ **
4775+ ** BTW, I _don't_ recommend you leave the socket open. If the socket variable
4776+ ** used for instanciation was discarded, there will not be any other
4777+ ** references to the socket save the one held privately, so a socket left
4778+ ** open will be there forever. This will almost certainly warrent an
4779+ ** unpleasent visit by one or more SAs of the box(es) hosting your
4780+ ** application over time.
4781+ **
4782+ ** autoclose=true; it's the only way to be sure. ;)
4783+ **/
4784+ tcp_socket(int existing_socket, bool autoclose=true);
4785+
4786+ /** Destructs a tcp_socket.
4787+ **
4788+ ** If autoclose was set to true, the socket will be closed if it is open
4789+ ** at the time of destruction. If no, the socket will be left in whatever
4790+ ** state it happened to be in at the time.
4791+ **/
4792+ virtual ~tcp_socket();
4793+
4794+ /** Resets the socket after a hard error.
4795+ **
4796+ ** In cases where the socket was invlidated by the operating system
4797+ ** (typically cases where a SIGPIPE was raised by the TCP/IP stack),
4798+ ** use this function to discard the old socket id and aquire a new one.
4799+ ** Understand that this will make the tcp_socket useful again, but you
4800+ ** will have to reconnect before any traffic can be sent.
4801+ **/
4802+ virtual void reset();
4803+
4804+ /** Creates a sockaddr_in from a formatted string.
4805+ **
4806+ ** address is an "IP:port" formatted string; i.e. 129.168.1.1:80.
4807+ ** "*" may use used to substatute for the IP, port or both.
4808+ **
4809+ ** Returns a properly formatted sockaddr_in struct for use with connect,
4810+ ** bind, etc. Throws a bad_address_exception if the address argument is
4811+ ** mal-formed.
4812+ **/
4813+ static sockaddr_in str_to_sockaddr(const std::string & address);
4814+
4815+ /** Creates a string from a sockaddr_in.
4816+ **
4817+ ** The returned string is of the same format accepted as arguments to the
4818+ ** to the bind() and connect() methods.
4819+ **
4820+ ** May throw a bad_address_exception if the sock_addr_in is not
4821+ ** properly formatted.
4822+ **/
4823+ static std::string sockaddr_to_str(const sockaddr_in & address);
4824+
4825+ /** binds the tcp_socket to a local address/port.
4826+ **
4827+ ** You do _not_ need to use this method if you are setting up a tcp_socket
4828+ ** for client use. If you don't call bind an ephemeral port and the host's
4829+ ** IP number will be assigned, as is normal and preferred for client sockets.
4830+ **
4831+ ** In very rare cases where you have a multi-homed host and a real
4832+ ** requirement to specify which IP this connection uses as local, you can
4833+ ** use this method to select the port and address the client will use.
4834+ **
4835+ ** address: string of the format IP:port; example "255.255.255.255:91".
4836+ ** If you wish to accept input on any active IP address in this host,
4837+ ** use "*" for the IP address, as in "*:80". If you want to fix the address
4838+ ** but leave the port up to the host, use "*" for the port, as in
4839+ ** "10.101.78.33:*". Obviously, using "*:*" as the address gives the
4840+ ** same results as not calling this method at all.
4841+ **
4842+ ** If the address argument is mal-formed a bad_address_exception will be
4843+ ** thrown and no changes will be made to the tcp_socket.
4844+ **
4845+ ** If the address is not bindable (already in use is a common cause) a
4846+ ** cant_bind_exception will be thrown.
4847+ **/
4848+ void bind(const std::string & address);
4849+
4850+ /** Opens the connection.
4851+ **
4852+ ** address: string of the format IP:port; example "255.255.255.255:91".
4853+ ** If the address is mal-formed a bad_address_exception will be thrown.
4854+ **
4855+ ** If timeout is specified and >0, the system will not wait more than
4856+ ** timeout seconds before throwing a timeout_exception.
4857+ **
4858+ ** If the connection is not set up properly, a bad_connection_exception
4859+ ** will be thrown.
4860+ **/
4861+ void connect(const std::string & address, int timeout=0);
4862+
4863+ /** Closes an open connection.
4864+ **
4865+ ** If a problem is reported a close_exception will be thrown. Possible
4866+ ** causes include the socket not being open, unsent data pending in the
4867+ ** tcp stack, etc.
4868+ **/
4869+ virtual void close();
4870+
4871+ /** Returns the current status.
4872+ **
4873+ ** Possibles states are tcp_socket::undef, tcp_socket::init,
4874+ ** tcp_socket::connect, and tcp_socket::close.
4875+ **/
4876+ state status() { return _status; };
4877+
4878+ /** Returns the last socket error recieved.
4879+ **
4880+ ** Will contain zero if no errors have occured on the socket since
4881+ ** the tcp_socket was instanciated, or the errno returned on the most recent
4882+ ** error otherwise.
4883+ **
4884+ ** Check the man pages for bind(), connect(), close(), socket(), send(),
4885+ ** and recv() for possible values. They are defined in error.h.
4886+ **/
4887+ int last_error() { return _last_error; };
4888+
4889+ /** Sends the string to the target host.
4890+ **
4891+ ** If timeout is specified and >0, a timeout_exception will be thrown
4892+ ** if the send does not succeed within timeout seconds.
4893+ **
4894+ ** If socket is not connected or closes during sending a
4895+ ** not_open_exception will be thrown.
4896+ **
4897+ ** If an exception is thrown, the characters that were not
4898+ ** sent will be available via the exception's comment() method (as
4899+ ** a string, of course).
4900+ **/
4901+ int put(std::string s, int timeout=10);
4902+
4903+ /** gets a string of characters from the socket.
4904+ **
4905+ ** This method allows the reception of a string of characters
4906+ ** limited by length and time. Use this method when you are expecting a
4907+ ** stream if data that you either know the length of or where there is
4908+ ** no specific ending character. If the expected traffic is organized
4909+ ** into messages or lines ending with a specific character or string,
4910+ ** use the getln() method instead.
4911+ **
4912+ ** Examples:
4913+ **
4914+ ** get() or get(1) will return a string containing a single
4915+ ** character or throw a timeout in 10 seconds if one is not
4916+ ** recieved.
4917+ **
4918+ ** get(100,30) will return when 100 characters have been recieved or
4919+ ** throw a timeout in 30 seconds.
4920+ **
4921+ ** get(100,-1) will return after 100 characters have been recieved, and will
4922+ ** _never_ time out. I strongly recommend that at the very least use timeout
4923+ ** values >= 0 to this method to prevent program long term program stalls.
4924+ **
4925+ ** If maxlen==0, this method will return immediately with whatever characters
4926+ ** happen to be in the socket's input buffer at the time.
4927+ **
4928+ ** If maxlen>0 and timeout<0, this method will block until maxlen characters
4929+ ** have been recieved and then return. NOTE: this method could block
4930+ ** forever if the sending host does not send maxlen characters and timeout
4931+ ** is < 0.
4932+ **
4933+ ** If maxlen>0 and timeout>0 this method will return upon recieving
4934+ ** maxlen characters or throw a timeout_exception after timeout seconds
4935+ ** have expired in the worse case.
4936+ **
4937+ ** In all cases the method returns a string containing the characters
4938+ ** recieved, if any.
4939+ **
4940+ ** If the timeout expires before the required number of characters are
4941+ ** recieved a timeout_exception will be thrown.
4942+ **
4943+ ** If the socket is not connected or closes while being read a
4944+ ** not_open_exception will be thrown.
4945+ **
4946+ ** If an exception is thrown, any characters already recieved
4947+ ** will be available via the exception's comment() method.
4948+ **/
4949+ std::string get(int maxlen=1, int timeout=10);
4950+
4951+ /** gets a string of characters from the socket.
4952+ **
4953+ ** This method is for the reception of messages (or lines) that have a
4954+ ** specific ending string. As such it considers the recept of maxlen
4955+ ** characters or a timeout without the designated eol string to be
4956+ ** a problem and will throw an exception in those cases. This behavor
4957+ ** differs from that of the get() method, which simply returns when it
4958+ ** has received its limit.
4959+ **
4960+ ** If there is no specific eol or eom string in your expected data
4961+ ** stream use the get() method instead.
4962+ **
4963+ ** Examples:
4964+ **
4965+ ** getln() will return all characters recieved up to and including the
4966+ ** first carrage return or throw a timeout if a carrage return is not
4967+ ** recieved after 10 seconds.
4968+ **
4969+ ** getln("</alert>") will return all characters recieved up to and
4970+ ** including "</alert>" or throw a timeout if "</alert>" is not recieved
4971+ ** within 10 seconds.
4972+ **
4973+ ** getln(":",30) will return all characters recieved up to and including
4974+ ** ":" if ":" is recieved by the 30th character. If 30 characters are recieved
4975+ ** before ":", an overrun_exception would be thrown. A timeout would be
4976+ ** thrown if ":" is not recieved within 10 seconds.
4977+ **
4978+ ** getln(":",30,20) would react exactly like getln(":",30) except the timeout
4979+ ** period would be 20 seconds instead of the default 10.
4980+ **
4981+ ** getln(":",30,-1) will react exactly like getln(":",30) except that no
4982+ ** timeout will ever be thrown. In this case, the method may block
4983+ ** forever if no ":" is received and it never receives 30 characters.
4984+ ** I strongly recommend that at the very least that timeout be a
4985+ ** value >= 0 to this method to prevent program long term program stalls.
4986+ **
4987+ ** If maxlen==0 and timeout<0, this method will block until the eol
4988+ ** string is recieved from the host or maxlen characters
4989+ ** have been recieved. and then return. NOTE: this method could block
4990+ ** forever if the sending host does not send maxlen characters or the
4991+ ** eol string and timeout is < 0;
4992+ **
4993+ ** If maxlen>0 and timeout>0 this method will return upon recieving the
4994+ ** eol string, when maxlen characters have be recieved or when
4995+ ** timeout seconds have expired.
4996+ **
4997+ ** In all cases the method returns a string containing the characters
4998+ ** recieved, if any, including the eol string.
4999+ **
5000+ ** If the timeout expires before eol is recieved or maxlen characters are
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches

to all changes: