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