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

Last change on this file since 13986 was 13908, checked in by tbretz, 13 years ago
Do not print events without descriptions - these events might be services.
File size: 8.2 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) : fAllowedStates(cmd.fAllowedStates),
125 fFunction(cmd.fFunction)
126{
127}
128
129// --------------------------------------------------------------------------
130//
131//! If the state is 0 or positive add it to fAllowedStates
132//!
133//! @param state
134//! The state which should be added
135//
136void EventImp::AddAllowedState(int state)
137{
138 if (state>=0)
139 fAllowedStates.push_back(state);
140}
141
142// --------------------------------------------------------------------------
143//
144//! Add all states in the string to fAllowedStates.
145//!
146//! @param states
147//! A string containing the states. They can either be separated by
148//! whitespaces or commas, e.g. "1 2 3 4" or "1, 7, 9, 10". Note that
149//! no real consistency check is done.
150//
151void EventImp::AddAllowedStates(const char *states)
152{
153 stringstream stream(states);
154
155 const bool sep = stream.str().find(',')==string::npos;
156
157 string buffer;
158 while (getline(stream, buffer, sep ? ' ' : ','))
159 AddAllowedState(stoi(buffer));
160}
161
162// --------------------------------------------------------------------------
163//
164//! Return whether the given state is in the list of allowed states.
165//!
166//! @param state
167//! The state to look for in fAllowedStates
168//!
169//! @returns
170//! If the given state is negative returns false. If the list of allowed
171//! states is empty return true. Otherwise return whether the state
172//! is found in fAllowedList or not.
173//
174bool EventImp::IsStateAllowed(int state) const
175{
176 // States with negative values are internal states and are
177 // never allowed
178 // if (state<0)
179 // return false;
180
181 // In case no allowed state is explicitly set
182 // all positive states are allowed
183 if (fAllowedStates.size()==0)
184 return true;
185
186 return find(fAllowedStates.begin(), fAllowedStates.end(), state)!=fAllowedStates.end();
187}
188
189// --------------------------------------------------------------------------
190//
191//! @returns the event data converted to a std::string. Trailing redundant
192//! \0's are removed.
193//!
194string EventImp::GetString() const
195{
196 size_t s = GetSize()-1;
197 while (s>0 && GetText()[s]==0)
198 s--;
199
200 return std::string(GetText(), s+1);
201}
202
203// --------------------------------------------------------------------------
204//
205//! Print the contents of the event to the given stream.
206//!
207//! @param out
208//! An ostream to which the output should be redirected.
209//!
210//! @param strip
211//! defines whether a possible SERVER name in the event name
212//! should be stripped or not.
213//!
214void EventImp::Print(ostream &out, bool strip) const
215{
216 if (GetDescription().empty())
217 return;
218
219 out << " -";
220
221 const string str = GetName();
222 if (!str.empty())
223 out << kBold << str.substr(strip?str.find_first_of('/')+1:0) << kReset << "-";
224
225 const string fmt = GetFormat();
226
227 if (!str.empty() && !fmt.empty())
228 out << " ";
229
230 if (!fmt.empty())
231 out << "[" << fmt << "]";
232
233 vector<Description> v = Description::SplitDescription(GetDescription());
234
235 if (!GetDescription().empty())
236 {
237 out << kBold;
238 for (vector<Description>::const_iterator j=v.begin()+1;
239 j!=v.end(); j++)
240 out << " <" << j->name << ">";
241 out << kReset;
242 }
243
244 for (unsigned int i=0; i<fAllowedStates.size(); i++)
245 out << " " << fAllowedStates[i];
246
247 const Time tm = GetTime();
248
249 const bool t = tm!=Time::None && tm!=Time(1970,1,1);
250 const bool s = GetSize()>0;
251
252 if (s || t)
253 out << "(";
254 if (t)
255 out << tm.GetAsStr("%H:%M:%S.%f");
256 if (s && t)
257 out << "/";
258 if (s)
259 out << "size=" << GetSize();
260 if (s || t)
261 out << ")";
262 out << endl;
263
264 if (GetDescription().empty())
265 {
266 out << endl;
267 return;
268 }
269
270 out << " " << v[0].comment << endl;
271
272 for (vector<Description>::const_iterator j=v.begin()+1;
273 j!=v.end(); j++)
274 {
275 out << " ||" << kGreen << j->name;
276 if (!j->comment.empty())
277 out << kReset << ": " << kBlue << j->comment;
278 if (!j->unit.empty())
279 out << kYellow << " [" << j->unit << "]";
280 out << endl;
281 }
282 out << endl;
283}
284
285// --------------------------------------------------------------------------
286//
287//! Calls Print(std::cout)
288//!
289//! @param strip
290//! defines whether a possible SERVER name in the event name
291//! should be stripped or not.
292//
293void EventImp::Print(bool strip) const
294{
295 Print(cout, strip);
296}
297
298string EventImp::GetTimeAsStr(const char *fmt) const
299{
300 return GetTime().GetAsStr(fmt);
301}
302
303uint64_t EventImp::GetJavaDate() const
304{
305 return GetTime().JavaDate();
306}
Note: See TracBrowser for help on using the repository browser.