Line data Source code
1 : //
2 : // DUNE DAQ modification notice:
3 : // This file has been modified from the original ATLAS genconfig source for the DUNE DAQ project.
4 : // Fork baseline commit: genconfig-03-10-00 (2021-04-26).
5 : // Renamed since fork: yes (from src/utils.cpp to apps/utils.cpp).
6 : //
7 :
8 :
9 : #include "class_info.hpp"
10 :
11 : #include "oks/kernel.hpp"
12 : #include "oks/method.hpp"
13 :
14 : #include <ctype.h>
15 :
16 : #include <algorithm>
17 : #include <ctime>
18 : #include <initializer_list>
19 : #include <iomanip>
20 : #include <iostream>
21 :
22 :
23 : using namespace dunedaq::oks;
24 : using namespace dunedaq::oksdalgen;
25 :
26 : /**
27 : * The functions cvt_symbol() and alnum_name() are used
28 : * to replace all symbols allowed in names of classes, attributes
29 : * and relationships, but misinterpreted by c++.
30 : */
31 :
32 : char
33 0 : cvt_symbol(char c)
34 : {
35 0 : return (isalnum(c) ? c : '_');
36 : }
37 :
38 : std::string
39 0 : alnum_name(const std::string& in)
40 : {
41 0 : std::string s(in);
42 0 : std::transform(s.begin(), s.end(), s.begin(), cvt_symbol);
43 0 : return s;
44 0 : }
45 :
46 : std::string
47 0 : capitalize_name(const std::string& in)
48 : {
49 0 : std::string s(in);
50 0 : if (!in.empty())
51 : {
52 0 : if (isalpha(in[0]))
53 : {
54 0 : if (islower(in[0]))
55 0 : s[0] = toupper(in[0]);
56 : }
57 : else
58 : {
59 0 : s.insert(s.begin(), '_');
60 : }
61 : }
62 0 : return s;
63 0 : }
64 :
65 :
66 : /**
67 : * The function print_description() is used for printing of the
68 : * multi-line text with right alignment.
69 : */
70 :
71 : void
72 0 : print_description(std::ostream& s, const std::string& text, const char * dx)
73 : {
74 0 : if (!text.empty())
75 : {
76 0 : s << dx << " /**\n";
77 :
78 0 : Oks::Tokenizer t(text, "\n");
79 0 : std::string token;
80 :
81 0 : while (!(token = t.next()).empty())
82 : {
83 0 : s << dx << " * " << token << std::endl;
84 : }
85 :
86 0 : s << dx << " */\n\n";
87 0 : }
88 0 : }
89 :
90 : void
91 0 : print_indented(std::ostream& s, const std::string& text, const char * dx)
92 : {
93 0 : if (!text.empty())
94 : {
95 0 : Oks::Tokenizer t(text, "\n");
96 0 : std::string token;
97 :
98 0 : while (!(token = t.next()).empty())
99 : {
100 0 : s << dx << token << std::endl;
101 : }
102 0 : }
103 0 : }
104 :
105 : std::string
106 0 : get_type(OksData::Type oks_type, bool is_cpp)
107 : {
108 0 : switch (oks_type)
109 : {
110 0 : case OksData::unknown_type:
111 0 : return "UNKNOWN";
112 0 : case OksData::s8_int_type:
113 0 : return (is_cpp ? "int8_t" : "char");
114 0 : case OksData::u8_int_type:
115 0 : return (is_cpp ? "uint8_t" : "byte");
116 0 : case OksData::s16_int_type:
117 0 : return (is_cpp ? "int16_t" : "short");
118 0 : case OksData::u16_int_type:
119 0 : return (is_cpp ? "uint16_t" : "short");
120 0 : case OksData::s32_int_type:
121 0 : return (is_cpp ? "int32_t" : "int");
122 0 : case OksData::u32_int_type:
123 0 : return (is_cpp ? "uint32_t" : "int");
124 0 : case OksData::s64_int_type:
125 0 : return (is_cpp ? "int64_t" : "long");
126 0 : case OksData::u64_int_type:
127 0 : return (is_cpp ? "uint64_t" : "long");
128 0 : case OksData::float_type:
129 0 : return "float";
130 0 : case OksData::double_type:
131 0 : return "double";
132 0 : case OksData::bool_type:
133 0 : return (is_cpp ? "bool" : "boolean");
134 :
135 0 : case OksData::string_type:
136 0 : case OksData::enum_type:
137 0 : case OksData::date_type:
138 0 : case OksData::time_type:
139 0 : case OksData::class_type:
140 0 : return (is_cpp ? "std::string" : "String");
141 :
142 0 : case OksData::object_type:
143 0 : case OksData::list_type:
144 0 : case OksData::uid_type:
145 0 : case OksData::uid2_type:
146 0 : return "funnytype";
147 : }
148 :
149 0 : return "invalid";
150 : }
151 :
152 : // std::string
153 : // get_java_impl_name(const std::string& s)
154 : // {
155 : // std::string str(s);
156 : // str += "_Impl";
157 : // return str;
158 : // }
159 :
160 : // std::string
161 : // get_java_helper_name(const std::string& s)
162 : // {
163 : // std::string str(s);
164 : // str += "_Helper";
165 : // return str;
166 : // }
167 :
168 : void
169 0 : gen_dump_application(std::ostream& s,
170 : std::list<std::string>& class_names,
171 : const std::string& cpp_ns_name,
172 : const std::string& cpp_hdr_dir,
173 : const char * conf_header,
174 : const char * conf_name,
175 : const char * headres_prologue,
176 : const char * main_function_prologue
177 : )
178 : {
179 0 : s <<
180 : " // *** this file is generated by oksdalgen ***\n"
181 : "\n"
182 : "#include \"conffwk/ConfigObject.hpp\"\n"
183 0 : "#include \"" << conf_header << "\"\n\n";
184 :
185 : // generate list of includes
186 0 : for (const auto& i : class_names)
187 : {
188 0 : std::string hname(cpp_hdr_dir);
189 0 : if (!hname.empty())
190 0 : hname += '/';
191 0 : hname += i;
192 0 : s << "#include \"" << hname << ".hpp\"\n";
193 0 : }
194 :
195 0 : if (headres_prologue && *headres_prologue)
196 : {
197 0 : s << "\n // db implementation-specific headrers prologue\n\n" << headres_prologue << "\n";
198 : }
199 :
200 0 : s <<
201 : "\n"
202 : "\n"
203 : "static void usage(const char * s)\n"
204 : "{\n"
205 : " std::cout << s << \" -d db-name -c class-name [-q query | -i object-id] [-t]\\n\"\n"
206 : " \"\\n\"\n"
207 : " \"Options/Arguments:\\n\"\n"
208 : " \" -d | --data db-name mandatory name of the database\\n\"\n"
209 : " \" -c | --class-name class-name mandatory name of class\\n\"\n"
210 : " \" -q | --query query optional query to select class objects\\n\"\n"
211 : " \" -i | --object-id object-id optional identity to select one object\\n\"\n"
212 : " \" -t | --init-children all referenced objects are initialized (is used\\n\"\n"
213 : " \" for debug purposes and performance measurements)\\n\"\n"
214 : " \" -h | --help print this message\\n\"\n"
215 : " \"\\n\"\n"
216 : " \"Description:\\n\"\n"
217 : " \" The program prints out object(s) of given class.\\n\"\n"
218 : " \" If no query or object id is provided, all objects of the class are printed.\\n\"\n"
219 : " \" It is automatically generated by oksdalgen utility.\\n\"\n"
220 : " \"\\n\";\n"
221 : "}\n"
222 : "\n"
223 : "static void no_param(const char * s)\n"
224 : "{\n"
225 : " std::cerr << \"ERROR: the required argument for option \\\'\" << s << \"\\\' is missing\\n\\n\";\n"
226 : " exit (EXIT_FAILURE);\n"
227 : "}\n"
228 : "\n"
229 : "int main(int argc, char *argv[])\n"
230 0 : "{\n";
231 :
232 0 : if (main_function_prologue && *main_function_prologue)
233 : {
234 0 : s << " // db implementation-specific main function prologue\n\n " << main_function_prologue << "\n\n";
235 : }
236 :
237 0 : s <<
238 : " // parse parameters\n"
239 : "\n"
240 : " const char * db_name = nullptr;\n"
241 : " const char * object_id = nullptr;\n"
242 : " const char * query = \"\";\n"
243 : " std::string class_name;\n"
244 : " bool init_children = false;\n"
245 : "\n"
246 : " for(int i = 1; i < argc; i++) {\n"
247 : " const char * cp = argv[i];\n"
248 : " if(!strcmp(cp, \"-h\") || !strcmp(cp, \"--help\")) {\n"
249 : " usage(argv[0]);\n"
250 : " return 0;\n"
251 : " }\n"
252 : " if(!strcmp(cp, \"-t\") || !strcmp(cp, \"--init-children\")) {\n"
253 : " init_children = true;\n"
254 : " }\n"
255 : " else if(!strcmp(cp, \"-d\") || !strcmp(cp, \"--data\")) {\n"
256 : " if(++i == argc || argv[i][0] == '-') { no_param(cp); } else { db_name = argv[i]; }\n"
257 : " }\n"
258 : " else if(!strcmp(cp, \"-c\") || !strcmp(cp, \"--class-name\")) {\n"
259 : " if(++i == argc || argv[i][0] == '-') { no_param(cp); } else { class_name = argv[i]; }\n"
260 : " }\n"
261 : " else if(!strcmp(cp, \"-i\") || !strcmp(cp, \"--object-id\")) {\n"
262 : " if(++i == argc || argv[i][0] == '-') { no_param(cp); } else { object_id = argv[i]; }\n"
263 : " }\n"
264 : " else if(!strcmp(cp, \"-q\") || !strcmp(cp, \"--query\")) {\n"
265 : " if(++i == argc || argv[i][0] == '-') { no_param(cp); } else { query = argv[i]; }\n"
266 : " }\n"
267 : " else {\n"
268 : " std::cerr << \"ERROR: bad parameter \" << cp << std::endl;\n"
269 : " usage(argv[0]);\n"
270 : " return (EXIT_FAILURE);\n"
271 : " }\n"
272 : " }\n"
273 : "\n"
274 : " if(db_name == nullptr) {\n"
275 : " std::cerr << \"ERROR: no database name provided\\n\";\n"
276 : " return (EXIT_FAILURE);\n"
277 : " }\n"
278 : "\n"
279 : " if(class_name.empty()) {\n"
280 : " std::cerr << \"ERROR: no class name provided\\n\";\n"
281 : " return (EXIT_FAILURE);\n"
282 : " }\n"
283 : "\n"
284 : " if(*query != 0 && object_id != nullptr) {\n"
285 : " std::cerr << \"ERROR: only one parameter -i or -q can be provided\\n\";\n"
286 : " return (EXIT_FAILURE);\n"
287 : " }\n"
288 : "\n"
289 : "\n"
290 : "std::cout << std::boolalpha;\n"
291 0 : "\n";
292 :
293 0 : if (conf_name)
294 : {
295 0 : s <<
296 : " " << conf_name << " impl_conf;\n"
297 : "\n"
298 : " {\n"
299 0 : " dunedaq::conffwk::Configuration conf(db_name, &impl_conf);\n";
300 : }
301 : else
302 : {
303 0 : s <<
304 : " try {\n"
305 0 : " dunedaq::conffwk::Configuration conf(db_name);\n";
306 : }
307 :
308 0 : s <<
309 : "\n"
310 : " if(!conf.loaded()) {\n"
311 : " std::cerr << \"Can not load database: \" << db_name << std::endl;\n"
312 : " return (EXIT_FAILURE);\n"
313 : " }\n"
314 : " \n"
315 : " std::vector< dunedaq::conffwk::ConfigObject > objects;\n"
316 : " \n"
317 : " if(object_id) {\n"
318 : " dunedaq::conffwk::ConfigObject obj;\n"
319 : " try {\n"
320 : " conf.get(class_name, object_id, obj, 1);\n"
321 : " }\n"
322 : " catch (dunedaq::conffwk::NotFound & ex) {\n"
323 : " std::cerr << \"Can not get object \\'\" << object_id << \"\\' of class \\'\" << class_name << \"\\':\\n\" << ex << std::endl;\n"
324 : " return (EXIT_FAILURE);\n"
325 : " }\n"
326 : " objects.push_back(obj);\n"
327 : " }\n"
328 : " else {\n"
329 : " try {\n"
330 : " conf.get(class_name, objects, query, 1);\n"
331 : " }\n"
332 : " catch (dunedaq::conffwk::NotFound & ex) {\n"
333 : " std::cerr << \"Can not get objects of class \\'\" << class_name << \"\\':\\n\" << ex << std::endl;\n"
334 : " return (EXIT_FAILURE);\n"
335 : " }\n"
336 : " }\n"
337 : " \n"
338 : " struct SortByUId {\n"
339 : " bool operator() (const dunedaq::conffwk::ConfigObject * o1, const dunedaq::conffwk::ConfigObject * o2) const {\n"
340 : " return (o1->UID() < o2->UID());\n"
341 : " };\n"
342 : " };\n"
343 : " \n"
344 : " std::set< dunedaq::conffwk::ConfigObject *, SortByUId > sorted_objects;\n"
345 : " \n"
346 : " for(auto& i : objects)\n"
347 : " sorted_objects.insert(&i);\n"
348 : " \n"
349 0 : " for(auto& i : sorted_objects) {\n";
350 :
351 0 : for (std::list<std::string>::iterator i = class_names.begin(); i != class_names.end(); ++i)
352 : {
353 0 : const char * op = (i == class_names.begin() ? "if" : "else if");
354 0 : std::string cname(cpp_ns_name);
355 :
356 0 : if (!cname.empty())
357 0 : cname += "::";
358 :
359 0 : cname += *i;
360 :
361 0 : s <<
362 : " " << op << "(class_name == \"" << *i << "\") {\n"
363 : " std::cout << *conf.get<" << cname << ">(*i, init_children) << std::endl;\n"
364 0 : " }\n";
365 0 : }
366 :
367 0 : s <<
368 : " else {\n"
369 : " std::cerr << \"ERROR: do not know how to dump object of \" << class_name << \" class\\n\";\n"
370 : " return (EXIT_FAILURE);\n"
371 : " }\n"
372 : " }\n"
373 : " }\n"
374 : " catch (dunedaq::conffwk::Exception & ex) {\n"
375 : " std::cerr << \"Caught \" << ex << std::endl;\n"
376 : " return (EXIT_FAILURE);\n"
377 : " }\n"
378 : "\n"
379 : " return 0;\n"
380 0 : "}\n";
381 0 : }
382 :
383 :
384 : void
385 0 : write_info_file(std::ostream& s,
386 : const std::string& cpp_namespace,
387 : const std::string& cpp_header_dir,
388 : // const std::string& java_pname,
389 : const std::set<const OksClass *, std::less<const OksClass *> >& classes)
390 : {
391 0 : std::time_t now = std::time(nullptr);
392 :
393 0 : s << "// the file is generated " << std::put_time(std::localtime(&now), "%F %T %Z") << " by oksdalgen utility\n"
394 : "// *** do not modify the file ***\n"
395 : "c++-namespace=" << cpp_namespace << "\n"
396 : "c++-header-dir-prefix=" << cpp_header_dir << "\n"
397 : // "java-package-name=" << java_pname << "\n"
398 0 : "classes:\n";
399 :
400 0 : for (const auto& i : classes)
401 0 : s << " " << i->get_name() << std::endl;
402 0 : }
403 :
404 :
405 : /**
406 : * The function get_full_cpp_class_name() returns name of class
407 : * with it's namespace (e.g. "NAMESPACE_A::CLASS_X")
408 : */
409 :
410 : std::string
411 0 : get_full_cpp_class_name(const OksClass * c, const ClassInfo::Map& cl_info, const std::string & cpp_ns_name)
412 : {
413 0 : std::string s;
414 0 : ClassInfo::Map::const_iterator idx = cl_info.find(c);
415 :
416 0 : if (idx != cl_info.end())
417 0 : s = (*idx).second.get_namespace();
418 : else
419 0 : s = cpp_ns_name;
420 :
421 0 : if (!s.empty())
422 0 : s += "::";
423 :
424 0 : s += alnum_name(c->get_name());
425 :
426 0 : return s;
427 0 : }
428 :
429 :
430 : std::string
431 0 : get_include_dir(const OksClass * c, const ClassInfo::Map& cl_info, const std::string& cpp_hdr_dir)
432 : {
433 0 : std::string s;
434 :
435 0 : ClassInfo::Map::const_iterator idx = cl_info.find(c);
436 :
437 0 : if (idx != cl_info.end())
438 : {
439 0 : const std::string include_prefix = (*idx).second.get_include_prefix();
440 0 : if (!include_prefix.empty())
441 : {
442 0 : s = include_prefix;
443 0 : s += '/';
444 : }
445 0 : }
446 0 : else if (!cpp_hdr_dir.empty())
447 : {
448 0 : s = cpp_hdr_dir;
449 0 : s += '/';
450 : }
451 :
452 0 : s += alnum_name(c->get_name());
453 :
454 0 : return s;
455 0 : }
456 :
457 :
458 : // const std::string&
459 : // get_package_name(const OksClass * c, const ClassInfo::Map& cl_info, const std::string& java_p_name)
460 : // {
461 : // std::string s;
462 :
463 : // ClassInfo::Map::const_iterator idx = cl_info.find(c);
464 :
465 : // if (idx != cl_info.end())
466 : // {
467 : // return (*idx).second.get_package_name();
468 : // }
469 : // else
470 : // {
471 : // return java_p_name;
472 : // }
473 : // }
474 :
475 : bool
476 0 : process_external_class(
477 : ClassInfo::Map& cl_info,
478 : const OksClass * c,
479 : const std::list<std::string>& include_dirs,
480 : const std::list<std::string>& user_classes,
481 : bool verbose)
482 : {
483 0 : if (cl_info.find(c) != cl_info.end())
484 : return true;
485 :
486 : // process list of user-defined classes first
487 :
488 0 : for (const auto &s : user_classes)
489 : {
490 0 : std::string::size_type idx = s.find("::");
491 0 : std::string::size_type idx2 = s.find("@", idx + 2);
492 :
493 0 : std::string cpp_ns_name;
494 0 : std::string class_name;
495 0 : std::string cpp_dir_name;
496 :
497 0 : if (idx == std::string::npos)
498 : {
499 0 : class_name = s.substr(0, idx2);
500 : }
501 : else
502 : {
503 0 : cpp_ns_name = s.substr(0, idx);
504 0 : class_name = s.substr(idx + 2, idx2 - idx - 2);
505 : }
506 :
507 0 : if (idx2 != std::string::npos)
508 0 : cpp_dir_name = s.substr(idx2 + 1);
509 :
510 0 : if (class_name == c->get_name())
511 : {
512 0 : cl_info[c] = ClassInfo(cpp_ns_name, cpp_dir_name);
513 0 : if (verbose)
514 : {
515 0 : std::cout << " * class " << c->get_name() << " is defined by user in ";
516 :
517 0 : if (cpp_ns_name.empty())
518 0 : std::cout << "global namespace";
519 : else
520 0 : std::cout << "namespace \"" << cpp_ns_name << '\"';
521 :
522 0 : if (!cpp_dir_name.empty())
523 0 : std::cout << " with \"" << cpp_dir_name << "\" include prefix";
524 :
525 0 : std::cout << std::endl;
526 : }
527 :
528 0 : return true;
529 : }
530 0 : }
531 :
532 : // process oksdalgen files
533 :
534 0 : if (verbose)
535 0 : std::cout << "Looking for oksdalgen info files ...\n";
536 :
537 0 : bool found_class_declaration = false;
538 :
539 0 : for (const auto& i : include_dirs)
540 : {
541 0 : std::string file_name(i);
542 0 : file_name += "/oksdalgen.info";
543 :
544 0 : std::ifstream f(file_name.c_str());
545 :
546 0 : if (f)
547 : {
548 0 : if (verbose)
549 0 : std::cout << " *** found file \"" << file_name << "\" ***\n";
550 :
551 0 : std::string cpp_ns_name;
552 0 : std::string cpp_dir_name;
553 : // std::string java_pname;
554 0 : bool is_class = false;
555 :
556 0 : std::string s;
557 0 : while (std::getline(f, s))
558 : {
559 0 : if (s.find("//") != std::string::npos)
560 : {
561 0 : if (verbose)
562 0 : std::cout << " - skip comment \"" << s << "\"\n";
563 : }
564 0 : else if (s.find("classes:") != std::string::npos)
565 : {
566 0 : if (verbose)
567 0 : std::cout << " - found classes keyword\n";
568 : is_class = true;
569 : }
570 : else
571 : {
572 0 : const char s1[] = "c++-namespace=";
573 0 : std::string::size_type idx = s.find(s1);
574 0 : if (idx != std::string::npos)
575 : {
576 0 : cpp_ns_name = s.substr(sizeof(s1) - 1);
577 0 : if (verbose)
578 0 : std::cout << " - c++ namespace = \"" << cpp_ns_name << "\"\n";
579 : }
580 : else
581 : {
582 0 : const char s2[] = "c++-header-dir-prefix=";
583 0 : std::string::size_type idx = s.find(s2);
584 0 : if (idx != std::string::npos)
585 : {
586 0 : cpp_dir_name = s.substr(sizeof(s2) - 1);
587 0 : if (verbose)
588 0 : std::cout << " - c++ header dir prefix name = \"" << cpp_dir_name << "\"\n";
589 : }
590 : // else
591 : // {
592 : // const char s3[] = "java-package-name=";
593 : // std::string::size_type idx = s.find(s3);
594 : // if (idx != std::string::npos)
595 : // {
596 : // java_pname = s.substr(sizeof(s3) - 1);
597 : // if (verbose)
598 : // std::cout << " - java package name = \"" << java_pname << "\"\n";
599 : // }
600 0 : else if (is_class)
601 : {
602 0 : std::string cname = s.substr(2);
603 0 : OksClass * cl = c->get_kernel()->find_class(cname);
604 0 : if (cl && cl_info.find(cl) == cl_info.end())
605 : {
606 0 : cl_info[cl] = ClassInfo(cpp_ns_name, cpp_dir_name);
607 0 : if (verbose)
608 0 : std::cout << " * class " << cl->get_name() << " is defined by " << file_name << " in namespace \"" << cpp_ns_name << "\" with include prefix \"" << cpp_dir_name << "\"\n";
609 0 : if (cl == c)
610 0 : found_class_declaration = true;
611 : }
612 0 : else if (verbose)
613 : {
614 0 : std::cout << " - skip class \"" << cname << "\" declaration\n";
615 : }
616 0 : }
617 : else
618 : {
619 0 : std::cerr << "Failed to parse line \"" << s << "\"\n";
620 : }
621 : // }
622 : }
623 : }
624 : }
625 0 : }
626 0 : else if (verbose)
627 : {
628 0 : std::cout << " *** file \"" << file_name << "\" does not exist ***\n";
629 : }
630 0 : }
631 :
632 0 : return found_class_declaration;
633 : }
634 :
635 : std::string
636 0 : int2dx(int level)
637 : {
638 0 : return std::string(level * 2, ' ');
639 : }
640 :
641 : int
642 0 : open_cpp_namespace(std::ostream& s, const std::string& value)
643 : {
644 0 : int level = 0;
645 0 : std::string dx;
646 :
647 0 : if (!value.empty())
648 : {
649 0 : Oks::Tokenizer t(value, ":");
650 0 : std::string token;
651 :
652 0 : while (!(token = t.next()).empty())
653 : {
654 0 : s << dx << "namespace " << token << " {\n";
655 0 : level++;
656 0 : dx += " ";
657 : }
658 0 : }
659 :
660 0 : return level;
661 0 : }
662 :
663 : void
664 0 : close_cpp_namespace(std::ostream& s, int level)
665 : {
666 0 : while (level > 0)
667 : {
668 0 : std::string dx = int2dx(--level);
669 0 : s << dx << "}\n";
670 0 : }
671 0 : }
672 :
673 :
674 :
675 : const std::string begin_header_prologue("BEGIN_HEADER_PROLOGUE");
676 : const std::string end_header_prologue("END_HEADER_PROLOGUE");
677 : const std::string begin_header_epilogue("BEGIN_HEADER_EPILOGUE");
678 : const std::string end_header_epilogue("END_HEADER_EPILOGUE");
679 : const std::string begin_public_section("BEGIN_PUBLIC_SECTION"); // => java interface
680 : const std::string end_public_section("END_PUBLIC_SECTION");
681 : const std::string begin_private_section("BEGIN_PRIVATE_SECTION"); // => c++ and java
682 : const std::string end_private_section("END_PRIVATE_SECTION");
683 : const std::string begin_member_initializer_list("BEGIN_MEMBER_INITIALIZER_LIST");
684 : const std::string end_member_initializer_list("END_MEMBER_INITIALIZER_LIST");
685 : const std::string has_add_algo_1("ADD_ALGO_1");
686 : const std::string has_add_algo_n("ADD_ALGO_N");
687 :
688 : static std::string
689 0 : get_method_header_x_logue(OksMethodImplementation * mi, const std::string& begin, const std::string& end)
690 : {
691 0 : std::string::size_type begix_idx = mi->get_body().find(begin, 0);
692 0 : if (begix_idx == std::string::npos)
693 0 : return "";
694 0 : std::string::size_type end_idx = mi->get_body().find(end, begix_idx + begin.size());
695 0 : if (end_idx == std::string::npos)
696 0 : return "";
697 0 : return mi->get_body().substr(begix_idx + begin.size(), end_idx - begix_idx - begin.size());
698 : }
699 :
700 : std::string
701 0 : get_method_header_prologue(OksMethodImplementation * mi)
702 : {
703 0 : return get_method_header_x_logue(mi, begin_header_prologue, end_header_prologue);
704 : }
705 :
706 : std::string
707 0 : get_method_header_epilogue(OksMethodImplementation * mi)
708 : {
709 0 : return get_method_header_x_logue(mi, begin_header_epilogue, end_header_epilogue);
710 : }
711 :
712 : std::string
713 0 : get_public_section(OksMethodImplementation * mi)
714 : {
715 0 : return get_method_header_x_logue(mi, begin_public_section, end_public_section);
716 : }
717 :
718 : std::string
719 0 : get_private_section(OksMethodImplementation * mi)
720 : {
721 0 : return get_method_header_x_logue(mi, begin_private_section, end_private_section);
722 : }
723 :
724 : std::string
725 0 : get_member_initializer_list(OksMethodImplementation * mi)
726 : {
727 0 : return get_method_header_x_logue(mi, begin_member_initializer_list, end_member_initializer_list);
728 : }
729 :
730 : bool
731 0 : get_add_algo_1(OksMethodImplementation * mi)
732 : {
733 0 : return (mi->get_body().find(has_add_algo_1, 0) != std::string::npos);
734 : }
735 :
736 : bool
737 0 : get_add_algo_n(OksMethodImplementation * mi)
738 : {
739 0 : return (mi->get_body().find(has_add_algo_n, 0) != std::string::npos);
740 : }
741 :
742 : static void
743 0 : remove_string_section(std::string& s, const std::string& begin, const std::string& end)
744 : {
745 0 : std::string::size_type begix_idx = s.find(begin, 0);
746 0 : if (begix_idx == std::string::npos)
747 : return;
748 :
749 0 : std::string::size_type end_idx = (end.empty() ? (begix_idx + begin.size()) : s.find(end, begix_idx + begin.size()));
750 0 : if (end_idx == std::string::npos)
751 : return;
752 :
753 0 : end_idx += end.size();
754 0 : while (s[end_idx] == '\n')
755 0 : end_idx++;
756 :
757 0 : s.erase(begix_idx, end_idx - begix_idx);
758 : }
759 :
760 : std::string
761 0 : get_method_implementation_body(OksMethodImplementation * mi)
762 : {
763 0 : std::string s = mi->get_body();
764 0 : remove_string_section(s, begin_header_prologue, end_header_prologue);
765 0 : remove_string_section(s, begin_header_epilogue, end_header_epilogue);
766 0 : remove_string_section(s, begin_public_section, end_public_section);
767 0 : remove_string_section(s, begin_private_section, end_private_section);
768 0 : remove_string_section(s, begin_member_initializer_list, end_member_initializer_list);
769 0 : remove_string_section(s, has_add_algo_1, "");
770 0 : remove_string_section(s, has_add_algo_n, "");
771 :
772 0 : if(std::all_of(s.begin(),s.end(),isspace))
773 0 : return "";
774 : else
775 0 : return s;
776 0 : }
777 :
778 : static OksMethodImplementation *
779 0 : find_method_implementation(const OksMethod * method, std::initializer_list<std::string> names)
780 : {
781 0 : for (const auto& name : names)
782 : {
783 0 : if (OksMethodImplementation * mi = method->find_implementation(name))
784 0 : if (mi->get_prototype().empty() == false)
785 : return mi;
786 : }
787 :
788 : return nullptr;
789 : }
790 :
791 : OksMethodImplementation *
792 0 : find_cpp_method_implementation(const OksMethod * method)
793 : {
794 0 : return find_method_implementation(method, { "c++", "C++" });
795 0 : }
796 :
|