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