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