source: trunk/FACT++/src/EventImp.cc@ 12350

Last change on this file since 12350 was 12128, checked in by tbretz, 13 years ago
Made pritning of event more compatible with help2man
File size: 8.1 KB
Line 
1// **************************************************************************
2/** @class EventImp
3
4@brief A general base-class describing events issues in a state machine
5
6@section General purpose
7
8The general purpose of this class is to describe an event which can
9occur in one of our StateMachines. It provides pointers to data
10associated with the event, a target state and stores the states in which
11issuing this event is allowed. The target state might be negative to
12describe that no transition of the state is requested.
13
14Such an event canjust be a description of an event, but can also be
15an issued event which already contain data.
16
17The format can, but need not, contain the format of the data area.
18As a rule, it should follow the format also used in the DIM network.
19
20
21@section Assigning functions to an event
22
23To any event a function call can be assigned. Thanks to boost::bind there
24are various and different very powerful ways to do that.
25
26The function assigned with AssignFunction must return int. When it is
27executed it is given a const reference of the current event as an argument,
28i.e. if you want to get such a reference in your function, you can reference
29it using the placeholder _1. (Remark: it is allowe to omit the _1 placeholder
30if no reference to the EventImp object is needed)
31
32A few examples:
33
34\code
35 int function(const EventImp &evt, int i, const char *txt) { return i; }
36
37 EventImp evt;
38 evt.AssignFunction(boost::bind(function, _1, 7, "hallo"));
39 cout << evt.Exec() << endl;
40 // 7
41\endcode
42
43When the function is executed later via ExecFunc() in will get a reference
44to the executing EventImp as its first argument (indicated by '_1'), it will
45get 7 and "hallo" as second and third argument.
46
47\code
48 int function(int i, const char *txt, const EventImp &evt) { return i; }
49
50 EventImp evt;
51 evt.AssignFunction(boost::bind(function, 7, "hallo", _1));
52 cout << evt.Exec() << endl;
53 // 7
54\endcode
55
56Is the same example than the one above, but the arguments are in a different
57order.
58
59\code
60 class A
61 {
62 int function(const EventImp &evt, int i, const char *txt)
63 {
64 cout << this << endl; return i;
65 }
66 };
67
68 A a;
69
70 EventImp evt;
71 evt.AssignFunction(boost::bind(&A::function, &a, _1, 7, "hallo"));
72 cout << evt.Exec() << endl;
73 // &a
74 // 7
75\endcode
76
77The advanatge of boost::bind is that it also works for member functions
78of classes. In this case the first argument after the function-pointer
79\b must be a pointer to a valid class-object. This can also be \em this
80if called from within a class object.
81
82Also note that everything (as usual) which is not a reference is copied
83when the bind function is invoked. If you want to distribute a reference
84instead use ref(something), like
85
86\code
87 int function(int &i) { return i; }
88
89 int j = 5;
90 EventImp evt;
91 evt.AssignFunction(bind(function, ref(j));
92 j = 7;
93 cout << evt.Exec() << endl;
94 // 7
95\endcode
96
97Note, that you are responsible for the validity, that means: Do not
98destroy your object (eg. reference to j) while bind might still be called
99later, or a pointer to \em this.
100
101@section References
102 - <A HREF="http://www.boost.org/doc/libs/1_45_0/libs/bind/bind.html">boost::bind (V1.45.0)</A>
103
104@todo
105 Add link to DIM format
106
107*/
108// **************************************************************************
109#include "EventImp.h"
110
111#include <sstream>
112
113#include "Time.h"
114#include "WindowLog.h"
115#include "Description.h"
116
117using namespace std;
118
119// --------------------------------------------------------------------------
120//
121//! Copy the contents of an EventImp (fTargetState, fAllowedStates and
122//! fFunction)
123//
124EventImp::EventImp(const EventImp &cmd) :
125 fTargetState(cmd.fTargetState), fAllowedStates(cmd.fAllowedStates),
126 fFunction(cmd.fFunction)
127{
128}
129
130// --------------------------------------------------------------------------
131//
132//! If the state is 0 or positive add it to fAllowedStates
133//!
134//! @param state
135//! The state which should be added
136//
137void EventImp::AddAllowedState(int state)
138{
139 if (state>=0)
140 fAllowedStates.push_back(state);
141}
142
143// --------------------------------------------------------------------------
144//
145//! Add all states in the string to fAllowedStates.
146//!
147//! @param states
148//! A string containing the states. They can either be separated by
149//! whitespaces or commas, e.g. "1 2 3 4" or "1, 7, 9, 10". Note that
150//! no real consistency check is done.
151//
152void EventImp::AddAllowedStates(const char *states)
153{
154 stringstream stream(states);
155
156 const bool sep = stream.str().find(',')==string::npos;
157
158 string buffer;
159 while (getline(stream, buffer, sep ? ' ' : ','))
160 AddAllowedState(stoi(buffer));
161}
162
163// --------------------------------------------------------------------------
164//
165//! Return whether the given state is in the list of allowed states.
166//!
167//! @param state
168//! The state to look for in fAllowedStates
169//!
170//! @returns
171//! If the given state is negative returns false. If the list of allowed
172//! states is empty return true. Otherwise return whether the state
173//! is found in fAllowedList or not.
174//
175bool EventImp::IsStateAllowed(int state) const
176{
177 // States with negative values are internal states and are
178 // never allowed
179 if (state<0)
180 return false;
181
182 // In case no allowed state is explicitly set
183 // all positive states are allowed
184 if (fAllowedStates.size()==0)
185 return true;
186
187 return find(fAllowedStates.begin(), fAllowedStates.end(), state)!=fAllowedStates.end();
188}
189
190// --------------------------------------------------------------------------
191//
192//! @returns the event data converted to a std::string. Trailing redundant
193//! \0's are removed.
194//!
195string EventImp::GetString() const
196{
197 size_t s = GetSize()-1;
198 while (s>0 && GetText()[s]==0)
199 s--;
200
201 return std::string(GetText(), s+1);
202}
203
204// --------------------------------------------------------------------------
205//
206//! Print the contents of the event to the given stream.
207//!
208//! @param out
209//! An ostream to which the output should be redirected.
210//!
211//! @param strip
212//! defines whether a possible SERVER name in the event name
213//! should be stripped or not.
214//!
215void EventImp::Print(ostream &out, bool strip) const
216{
217 out << " -";
218
219 const string str = GetName();
220 if (!str.empty())
221 out << kBold << str.substr(strip?str.find_first_of('/')+1:0) << kReset << "-";
222
223 const string fmt = GetFormat();
224
225 if (!str.empty() && !fmt.empty())
226 out << " ";
227
228 if (!fmt.empty())
229 out << "[" << fmt << "]";
230
231 vector<Description> v = Description::SplitDescription(GetDescription());
232
233 if (!GetDescription().empty())
234 {
235 out << kBold;
236 for (vector<Description>::const_iterator j=v.begin()+1;
237 j!=v.end(); j++)
238 out << " <" << j->name << ">";
239 out << kReset;
240 }
241
242 for (unsigned int i=0; i<fAllowedStates.size(); i++)
243 out << " " << fAllowedStates[i];
244
245 if (fTargetState<0)
246 out << " (conf)";
247 else
248 out << " (trans->" << fTargetState << ")";
249
250 const Time tm = GetTime();
251
252 const bool t = tm!=Time::None && tm!=Time(1970,1,1);
253 const bool s = GetSize()>0;
254
255 if (s || t)
256 out << "(";
257 if (t)
258 out << tm.GetAsStr("%H:%M:%S.%f");
259 if (s && t)
260 out << "/";
261 if (s)
262 out << "size=" << GetSize();
263 if (s || t)
264 out << ")";
265 out << endl;
266
267 if (GetDescription().empty())
268 {
269 out << endl;
270 return;
271 }
272
273 out << " " << v[0].comment << endl;
274
275 for (vector<Description>::const_iterator j=v.begin()+1;
276 j!=v.end(); j++)
277 {
278 out << " ||" << kGreen << j->name;
279 if (!j->comment.empty())
280 out << kReset << ": " << kBlue << j->comment;
281 if (!j->unit.empty())
282 out << kYellow << " [" << j->unit << "]";
283 out << endl;
284 }
285 out << endl;
286}
287
288// --------------------------------------------------------------------------
289//
290//! Calls Print(std::cout)
291//!
292//! @param strip
293//! defines whether a possible SERVER name in the event name
294//! should be stripped or not.
295//
296void EventImp::Print(bool strip) const
297{
298 Print(cout, strip);
299}
Note: See TracBrowser for help on using the repository browser.