DUNE-DAQ
DUNE Trigger and Data Acquisition software
Loading...
Searching...
No Matches
method.cpp
Go to the documentation of this file.
1// DUNE DAQ modification notice:
2// This file has been modified from the original ATLAS oks source for the DUNE DAQ project.
3// Fork baseline commit: oks-08-03-04 (2022-04-14).
4// Renamed since fork: no.
5
6#define _OksBuildDll_
7
8#include "oks/method.hpp"
9#include "oks/class.hpp"
10#include "oks/cstring.hpp"
11#include "oks/xml.hpp"
12
13#include <sstream>
14#include <stdexcept>
15
16namespace dunedaq {
17namespace oks {
18
19const char OksMethodImplementation::method_impl_xml_tag[] = "method-implementation";
20const char OksMethodImplementation::language_xml_attr[] = "language";
21const char OksMethodImplementation::prototype_xml_attr[] = "prototype";
22const char OksMethodImplementation::body_xml_attr[] = "body";
23
24const char OksMethod::method_xml_tag[] = "method";
25const char OksMethod::name_xml_attr[] = "name";
26const char OksMethod::description_xml_attr[] = "description";
27
29 const std::string& prototype,
30 const std::string& body,
31 OksMethod* p)
32 : p_language(language)
33 , p_prototype(prototype)
34 , p_body(body)
35 , p_method(p)
36{
37 oks::validate_not_empty(p_language, "method implementation language");
38 oks::validate_not_empty(p_prototype, "method implementation prototype");
39}
40
41bool
43{
44 return ((this == &i) || (p_language == i.p_language && p_prototype == i.p_prototype && p_body == i.p_body));
45}
46
47std::ostream&
48operator<<(std::ostream& s, const OksMethodImplementation& i)
49{
50 s << " Method implementation:\n"
51 " language: \""
52 << i.get_language()
53 << "\"\n"
54 " prototype: \""
55 << i.get_prototype()
56 << "\"\n"
57 " body: \""
58 << i.get_body() << "\"\n";
59
60 return s;
61}
62
63void
65{
66 s.put(" ");
67
68 s.put_start_tag(method_impl_xml_tag, sizeof(method_impl_xml_tag) - 1);
69
70 s.put_attribute(language_xml_attr, sizeof(language_xml_attr) - 1, get_language().c_str());
71 s.put_attribute(prototype_xml_attr, sizeof(prototype_xml_attr) - 1, get_prototype().c_str());
72 s.put_attribute(body_xml_attr, sizeof(body_xml_attr) - 1, get_body().c_str());
73
74 s.put_end_tag();
75}
76
78 : p_method(parent)
79{
80 try {
81 while (true) {
82 OksXmlAttribute attr(s);
83
84 // check for close of tag
85
86 if (oks::cmp_str1(attr.name(), "/")) {
87 break;
88 }
89
90 // check for known oks-method-implementation' attributes
91
92 else if (oks::cmp_str8(attr.name(), language_xml_attr))
93 p_language.assign(attr.value(), attr.value_len());
94 else if (oks::cmp_str9(attr.name(), prototype_xml_attr))
95 p_prototype.assign(attr.value(), attr.value_len());
96 else if (oks::cmp_str4(attr.name(), body_xml_attr))
97 p_body.assign(attr.value(), attr.value_len());
98 else {
99 s.throw_unexpected_attribute(attr.name());
100 }
101 }
102 } catch (oks::exception& e) {
103 throw oks::FailedRead("xml method implementation", e);
104 } catch (std::exception& e) {
105 throw oks::FailedRead("xml method implementation", e.what());
106 }
107
108 try {
109 oks::validate_not_empty(p_language, "method implementation language");
110 oks::validate_not_empty(p_prototype, "method implementation prototype");
111 } catch (std::exception& ex) {
112 throw oks::FailedRead("oks method implementation", oks::BadFileData(ex.what(), s.get_line_no(), s.get_line_pos()));
113 }
114}
115
116OksMethod::OksMethod(const std::string& nm, OksClass* p)
117 : p_class(p)
118 , p_name(nm)
119 , p_implementations(nullptr)
120{
121 try {
122 oks::validate_not_empty(p_name, "method name");
123 } catch (std::exception& ex) {
124 Oks::error_msg("OksMethod::OksMethod()") << ex.what() << std::endl;
125 }
126}
127
128OksMethod::OksMethod(const std::string& nm, const std::string& desc, OksClass* p)
129 : p_class(p)
130 , p_name(nm)
131 , p_description(desc)
132 , p_implementations(nullptr)
133{
134 oks::validate_not_empty(p_name, "method name");
135}
136
138{
139 if (p_implementations) {
140 while (!p_implementations->empty()) {
142 p_implementations->pop_front();
143 delete i;
144 }
145
146 delete p_implementations;
147 }
148}
149
150bool
151OksMethod::operator==(const class OksMethod& m) const
152{
153 // check if compare with self
154
155 if (this == &m)
156 return true;
157
158 // check if attributes are different
159
160 if (p_name != m.p_name || p_description != m.p_description)
161 return false;
162
163 // check if methods have no implementations
164
165 if (p_implementations == 0 && m.p_implementations == 0)
166 return true;
167
168 // check if only one method has implementation
169
170 if (p_implementations == 0 || m.p_implementations == 0)
171 return false;
172
173 // check if numbers of implementations are different
174
175 if (p_implementations->size() != m.p_implementations->size())
176 return false;
177
178 // check implementations
179
180 std::list<OksMethodImplementation*>::const_iterator i1 = p_implementations->begin();
181 std::list<OksMethodImplementation*>::const_iterator i2 = m.p_implementations->begin();
182
183 for (; i1 != p_implementations->end(); ++i1, ++i2) {
184 if (!(*(*i1) == *(*i2)))
185 return false;
186 }
187
188 return true;
189}
190
191std::ostream&
192operator<<(std::ostream& s, const OksMethod& m)
193{
194 s << "Method name: \"" << m.p_name
195 << "\"\n"
196 " description: \""
197 << m.p_description << "\"\n";
198
199 if (m.p_implementations) {
200 s << " implementations:\n";
201
202 for (std::list<OksMethodImplementation*>::const_iterator i = m.p_implementations->begin();
203 i != m.p_implementations->end();
204 ++i)
205 s << *(*i);
206 } else
207 s << " there are no implementation(s)\n";
208
209 return s;
210}
211
212void
214{
215 s.put_raw(' ');
216 s.put_raw(' ');
217
218 s.put_start_tag(method_xml_tag, sizeof(method_xml_tag) - 1);
219
220 s.put_attribute(name_xml_attr, sizeof(name_xml_attr) - 1, p_name.c_str());
221 s.put_attribute(description_xml_attr, sizeof(description_xml_attr) - 1, p_description.c_str());
222
223 s.put_raw('>');
224 s.put_raw('\n');
225
226 if (p_implementations) {
227 for (std::list<OksMethodImplementation*>::iterator i = p_implementations->begin(); i != p_implementations->end();
228 ++i)
229 (*i)->save(s);
230 }
231
232 s.put_raw(' ');
233 s.put_raw(' ');
234
235 s.put_last_tag(method_xml_tag, sizeof(method_xml_tag) - 1);
236}
237
239 : p_class(parent)
241{
242 try {
243 while (true) {
244 OksXmlAttribute attr(s);
245
246 // check for close of tag
247
248 if (oks::cmp_str1(attr.name(), ">")) {
249 break;
250 }
251
252 // check for known oks-relationship' attributes
253
254 else if (oks::cmp_str4(attr.name(), name_xml_attr))
255 p_name.assign(attr.value(), attr.value_len());
256 else if (oks::cmp_str11(attr.name(), description_xml_attr))
257 p_description.assign(attr.value(), attr.value_len());
258 else {
259 s.throw_unexpected_attribute(attr.name());
260 }
261 }
262 } catch (oks::exception& e) {
263 throw oks::FailedRead("xml method", e);
264 } catch (std::exception& e) {
265 throw oks::FailedRead("xml method", e.what());
266 }
267
268 // check validity of read values
269
270 try {
271 oks::validate_not_empty(p_name, "method name");
272 } catch (std::exception& ex) {
273 throw oks::FailedRead("oks method", oks::BadFileData(ex.what(), s.get_line_no(), s.get_line_pos()));
274 }
275
276 // read 'body' and 'method-actions'
277
278 {
279 while (true)
280 try {
281 const char* tag_start = s.get_tag_start();
282
283 if (oks::cmp_str7(tag_start, "/method")) {
284 break;
285 }
286
287 else if (!strcmp(tag_start, "method-implementation")) {
289 p_implementations = new std::list<OksMethodImplementation*>();
290 p_implementations->push_back(new OksMethodImplementation(s, this));
291 }
292
293 else {
294 std::ostringstream text;
295 text << "Unexpected tag \'" << tag_start << "\' inside method \'" << p_name << "\'\n";
296 throw std::runtime_error(text.str().c_str());
297 }
298
299 } catch (oks::exception& e) {
300 throw oks::FailedRead("method tag", e);
301 } catch (std::exception& e) {
302 throw oks::FailedRead("method tag", e.what());
303 }
304 }
305}
306
307void
308OksMethod::set_name(const std::string& new_name)
309{
310 // ignore when name is the same
311
312 if (p_name == new_name)
313 return;
314
315 // additional checks are required,
316 // if the method already belongs to some class
317
318 if (p_class) {
319
320 // check allowed length for attribute name
321
322 try {
323 oks::validate_not_empty(new_name, "name");
324 } catch (std::exception& ex) {
325 throw oks::SetOperationFailed("OksMethod::set_name", ex.what());
326 }
327
328 // having a direct method with the same name is an error
329
330 if (p_class->find_direct_method(new_name) != 0) {
331 std::ostringstream text;
332 text << "Class \"" << p_class->get_name() << "\" already has direct method \"" << new_name << '\"';
333 throw oks::SetOperationFailed("OksMethod::set_name", text.str());
334 }
335
336 // check that it is possible to lock the file
337
338 p_class->lock_file("OksMethod::set_name");
339
340 // probably a non-direct method already exists
341
342 OksMethod* m = p_class->find_method(new_name);
343
344 // change the name
345
346 p_name = new_name;
347
348 // registrate the change
349
351 } else {
352 p_name = new_name;
353 }
354}
355
357OksMethod::find_implementation(const std::string& language) const
358{
359 if (p_implementations) {
360 for (std::list<OksMethodImplementation*>::iterator i = p_implementations->begin(); i != p_implementations->end();
361 ++i)
362 if (language == (*i)->get_language())
363 return *i;
364 }
365
366 return 0;
367}
368
369void
370OksMethod::add_implementation(const std::string& language, const std::string& prototype, const std::string& body)
371{
372 if (find_implementation(language)) {
373 std::ostringstream text;
374 text << "Cannot add implementation on language \"" << language << "\" since it already exists.";
375 throw oks::SetOperationFailed("OksMethod::add_implementation", text.str());
376 }
377
378 if (p_class)
379 p_class->lock_file("OksMethod::add_implementation");
380
381 if (!p_implementations) {
382 p_implementations = new std::list<OksMethodImplementation*>();
383 }
384
385 OksMethodImplementation* i = new OksMethodImplementation(language, prototype, body);
386
387 p_implementations->push_back(i);
388 i->p_method = this;
389
390 if (p_class)
392}
393
394void
395OksMethod::remove_implementation(const std::string& language)
396{
398
399 if (i == 0) {
400 std::ostringstream text;
401 text << "Cannot remove implementation on language \"" << language << "\" since it does not exist.";
402 throw oks::SetOperationFailed("OksMethod::remove_implementation", text.str());
403 }
404
405 if (p_class)
406 p_class->lock_file("OksMethod::remove_implementation");
407
408 p_implementations->remove(i);
409
410 if (p_implementations->empty()) {
411 delete p_implementations;
413 }
414
415 if (p_class)
417}
418
419void
420OksMethod::set_description(const std::string& desc)
421{
422 if (p_description != desc) {
423 if (p_class)
424 p_class->lock_file("OksMethod::set_description");
425
426 p_description = desc;
427
428 if (p_class)
430 }
431}
432
433void
435{
436 if (p_language != s) {
437 if (p_method) {
438 if (p_method->find_implementation(s) != 0) {
439 std::ostringstream text;
440 text << "cannot rename \"" << p_method->p_name << "\" method implementation to language \"" << s
441 << "\" "
442 "since the method already has implementation with such language.";
443 throw oks::SetOperationFailed("OksMethodImplementation::set_language", text.str());
444 }
445
446 try {
447 oks::validate_not_empty(s, "language");
448 } catch (std::exception& ex) {
449 throw oks::SetOperationFailed("OksMethodImplementation::set_language", ex.what());
450 }
451
452 if (p_method->p_class)
453 p_method->p_class->lock_file("OksMethodImplementation::set_language");
454 }
455
456 p_language = s;
457
458 if (p_method && p_method->p_class) {
460 }
461 }
462}
463
464void
466{
467 if (p_prototype != s) {
468 try {
469 oks::validate_not_empty(s, "prototype");
470 } catch (std::exception& ex) {
471 throw oks::SetOperationFailed("OksMethodImplementation::set_prototype", ex.what());
472 }
473
474 if (p_method && p_method->p_class)
475 p_method->p_class->lock_file("OksMethodImplementation::set_prototype");
476
477 p_prototype = s;
478
479 if (p_method && p_method->p_class) {
481 }
482 }
483}
484
485void
487{
488 if (p_body != s) {
489 if (p_method && p_method->p_class)
490 p_method->p_class->lock_file("OksMethodImplementation::set_body");
491
492 p_body = s;
493
494 if (p_method && p_method->p_class) {
496 }
497 }
498}
499
500} // namespace oks
501} // namespace dunedaq
OksMethod * find_method(const std::string &name) const noexcept
Find method (search in this and base classes).
Definition class.cpp:1302
void registrate_class_change(ChangeType, const void *, bool=true)
Definition class.cpp:2009
const std::string & get_name() const noexcept
Definition class.hpp:374
void lock_file(const char *)
Definition class.cpp:733
OksMethod * find_direct_method(const std::string &name) const noexcept
Find direct method.
Definition class.cpp:1290
OKS method implementation class.
Definition method.hpp:39
const std::string & get_body() const noexcept
Definition method.hpp:101
OksMethodImplementation(const std::string &language, const std::string &prototype, const std::string &body, OksMethod *p=nullptr)
OKS method implementation constructor.
Definition method.cpp:28
friend std::ostream & operator<<(std::ostream &, const OksMethodImplementation &)
Definition method.cpp:48
const std::string & get_language() const noexcept
Definition method.hpp:69
void set_prototype(const std::string &prototype)
Set method implementation prototype.
Definition method.cpp:465
const std::string & get_prototype() const noexcept
Definition method.hpp:86
void set_language(const std::string &language)
Set method implementation language.
Definition method.cpp:434
bool operator==(const class OksMethodImplementation &) const
Definition method.cpp:42
static const char prototype_xml_attr[]
Definition method.hpp:130
void save(OksXmlOutputStream &) const
Definition method.cpp:64
static const char language_xml_attr[]
Definition method.hpp:129
void set_body(const std::string &body)
Set method implementation body.
Definition method.cpp:486
static const char body_xml_attr[]
Definition method.hpp:131
static const char method_impl_xml_tag[]
Definition method.hpp:128
friend class OksClass
Definition method.hpp:149
void set_name(const std::string &name)
Set method name.
Definition method.cpp:308
static const char name_xml_attr[]
Definition method.hpp:269
static const char description_xml_attr[]
Definition method.hpp:270
static const char method_xml_tag[]
Definition method.hpp:268
void set_description(const std::string &description)
Set method description.
Definition method.cpp:420
friend std::ostream & operator<<(std::ostream &, const OksMethod &)
Definition method.cpp:192
std::list< OksMethodImplementation * > * p_implementations
Definition method.hpp:259
void add_implementation(const std::string &language, const std::string &prototype, const std::string &body)
Add method implementation.
Definition method.cpp:370
void remove_implementation(const std::string &language)
Remove method implementation.
Definition method.cpp:395
bool operator==(const class OksMethod &) const
Definition method.cpp:151
friend class OksMethodImplementation
Definition method.hpp:150
OksMethodImplementation * find_implementation(const std::string &language) const
Find method implementation.
Definition method.cpp:357
void save(OksXmlOutputStream &) const
Definition method.cpp:213
std::string p_description
Definition method.hpp:258
OksMethod(const std::string &name, OksClass *p=nullptr)
OKS method constructor.
Definition method.cpp:116
static std::ostream & error_msg(const char *)
Definition kernel.cpp:511
virtual const char * what() const noexcept
bool cmp_str8(const char *s1, const char s2[9])
Definition cstring.hpp:93
bool cmp_str1(const char *s1, const char s2[2])
Definition cstring.hpp:15
bool cmp_str4(const char *s1, const char s2[5])
Definition cstring.hpp:45
bool cmp_str9(const char *s1, const char s2[10])
Definition cstring.hpp:105
void validate_not_empty(const std::string &value, const char *name)
bool cmp_str11(const char *s1, const char s2[12])
Definition cstring.hpp:117
bool cmp_str7(const char *s1, const char s2[8])
Definition cstring.hpp:81
The DUNE-DAQ namespace.
Definition ral.hpp:59
size_t value_len() const
Definition xml.hpp:288