00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "cpp_generator.h"
00024 #include "exceptions.h"
00025
00026 #include <utils/misc/string_conversions.h>
00027
00028 #include <algorithm>
00029 #include <iostream>
00030 #include <vector>
00031 #include <time.h>
00032 #include <fstream>
00033
00034 using namespace std;
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058 CppInterfaceGenerator::CppInterfaceGenerator(std::string directory, std::string interface_name,
00059 std::string config_basename, std::string author,
00060 std::string year, std::string creation_date,
00061 std::string data_comment,
00062 const unsigned char *hash, size_t hash_size,
00063 const std::vector<InterfaceConstant> &constants,
00064 const std::vector<InterfaceEnumConstant> &enum_constants,
00065 const std::vector<InterfaceField> &data_fields,
00066 const std::vector<InterfacePseudoMap> &pseudo_maps,
00067 const std::vector<InterfaceMessage> &messages
00068 )
00069 {
00070 this->dir = directory;
00071 if ( dir.find_last_of("/") != (dir.length() - 1) ) {
00072 dir += "/";
00073 }
00074 this->author = author;
00075 this->year = year;
00076 this->creation_date = creation_date;
00077 this->data_comment = data_comment;
00078 this->hash = hash;
00079 this->hash_size = hash_size;
00080 this->constants = constants;
00081 this->enum_constants = enum_constants;
00082 this->data_fields = data_fields;
00083 this->pseudo_maps = pseudo_maps;
00084 this->messages = messages;
00085
00086 filename_cpp = config_basename + ".cpp";
00087 filename_h = config_basename + ".h";
00088 filename_o = config_basename + ".o";
00089
00090 if ( interface_name.find("Interface", 0) == string::npos ) {
00091
00092 class_name = interface_name + "Interface";
00093 } else {
00094 class_name = interface_name;
00095 }
00096
00097 deflector = "__INTERFACES_" + fawkes::StringConversions::to_upper(config_basename) + "_H_";
00098 }
00099
00100
00101
00102 CppInterfaceGenerator::~CppInterfaceGenerator()
00103 {
00104 }
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124 void
00125 CppInterfaceGenerator::write_struct(FILE *f, std::string name, std::string is,
00126 std::vector<InterfaceField> fields)
00127 {
00128
00129 stable_sort(fields.begin(), fields.end());
00130
00131 if ( fields.size() > 0 ) {
00132
00133 fprintf(f,
00134 "%s/** Internal data storage, do NOT modify! */\n"
00135 "%stypedef struct {\n", is.c_str(), is.c_str());
00136
00137 for (vector<InterfaceField>::iterator i = fields.begin(); i != fields.end(); ++i) {
00138 fprintf(f, "%s %s %s", is.c_str(), (*i).getStructType().c_str(), (*i).getName().c_str());
00139 if ( (*i).getLength().length() > 0 ) {
00140 fprintf(f, "[%s]", (*i).getLength().c_str());
00141 }
00142 fprintf(f, "; /**< %s */\n", (*i).getComment().c_str());
00143 }
00144
00145 fprintf(f, "%s} %s;\n\n", is.c_str(), name.c_str());
00146 }
00147 }
00148
00149
00150
00151
00152
00153
00154 void
00155 CppInterfaceGenerator::write_header(FILE *f, std::string filename)
00156 {
00157 fprintf(f,
00158 "\n/***************************************************************************\n"
00159 " * %s - Fawkes BlackBoard Interface - %s\n"
00160 " *\n"
00161 "%s%s%s"
00162 " * Templated created: Thu Oct 12 10:49:19 2006\n"
00163 " * Copyright %s %s\n"
00164 " *\n"
00165 " ****************************************************************************/\n\n"
00166 "/* This program is free software; you can redistribute it and/or modify\n"
00167 " * it under the terms of the GNU General Public License as published by\n"
00168 " * the Free Software Foundation; either version 2 of the License, or\n"
00169 " * (at your option) any later version. A runtime exception applies to\n"
00170 " * this software (see LICENSE.GPL_WRE file mentioned below for details).\n"
00171 " *\n"
00172 " * This program is distributed in the hope that it will be useful,\n"
00173 " * but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
00174 " * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
00175 " * GNU Library General Public License for more details.\n"
00176 " *\n"
00177 " * Read the full text in the LICENSE.GPL_WRE file in the doc directory.\n"
00178 " */\n\n",
00179 filename.c_str(), class_name.c_str(),
00180 (creation_date.length() > 0 ) ? " * Interface created: " : "",
00181 (creation_date.length() > 0 ) ? creation_date.c_str() : "",
00182 (creation_date.length() > 0 ) ? "\n" : "",
00183 year.c_str(), (author.length() > 0) ? author.c_str() : "AllemaniACs RoboCup Team"
00184 );
00185 }
00186
00187
00188
00189
00190
00191 void
00192 CppInterfaceGenerator::write_deflector(FILE *f)
00193 {
00194 fprintf(f, "#ifndef %s\n", deflector.c_str());
00195 fprintf(f, "#define %s\n\n", deflector.c_str());
00196 }
00197
00198
00199
00200
00201
00202 void
00203 CppInterfaceGenerator::write_cpp(FILE *f)
00204 {
00205 write_header(f, filename_cpp);
00206 fprintf(f,
00207 "#include <interfaces/%s>\n\n"
00208 "#include <core/exceptions/software.h>\n\n"
00209 "#include <cstring>\n"
00210 "#include <cstdlib>\n\n"
00211 "namespace fawkes {\n\n"
00212 "/** @class %s <interfaces/%s>\n"
00213 " * %s Fawkes BlackBoard Interface.\n"
00214 " * %s\n"
00215 " * @ingroup FawkesInterfaces\n"
00216 " */\n\n\n",
00217 filename_h.c_str(), class_name.c_str(), filename_h.c_str(),
00218 class_name.c_str(), data_comment.c_str());
00219 write_constants_cpp(f);
00220 write_ctor_dtor_cpp(f, class_name, "Interface", "", data_fields, messages);
00221 write_methods_cpp(f, class_name, class_name, data_fields, pseudo_maps, "");
00222 write_basemethods_cpp(f);
00223 write_messages_cpp(f);
00224
00225 write_management_funcs_cpp(f);
00226
00227 fprintf(f, "\n} // end namespace fawkes\n");
00228 }
00229
00230
00231
00232
00233
00234 void
00235 CppInterfaceGenerator::write_management_funcs_cpp(FILE *f)
00236 {
00237 fprintf(f,
00238 "/// @cond INTERNALS\n"
00239 "EXPORT_INTERFACE(%s)\n"
00240 "/// @endcond\n\n",
00241 class_name.c_str());
00242 }
00243
00244
00245
00246
00247
00248 void
00249 CppInterfaceGenerator::write_constants_cpp(FILE *f)
00250 {
00251 for ( vector<InterfaceConstant>::iterator i = constants.begin(); i != constants.end(); ++i) {
00252 fprintf(f,
00253 "/** %s constant */\n"
00254 "const %s %s::%s = %s;\n",
00255 (*i).getName().c_str(),
00256 (*i).getType().c_str(),
00257 class_name.c_str(), (*i).getName().c_str(), (*i).getValue().c_str());
00258 }
00259 fprintf(f, "\n");
00260 }
00261
00262
00263
00264
00265
00266 void
00267 CppInterfaceGenerator::write_constants_h(FILE *f)
00268 {
00269 fprintf(f, " /* constants */\n");
00270 for ( vector<InterfaceConstant>::iterator i = constants.begin(); i != constants.end(); ++i) {
00271 fprintf(f, " static const %s %s;\n", (*i).getType().c_str(), (*i).getName().c_str());
00272 }
00273 fprintf(f, "\n");
00274
00275 for ( vector<InterfaceEnumConstant>::iterator i = enum_constants.begin(); i != enum_constants.end(); ++i) {
00276 fprintf(f,
00277 " /** %s */\n"
00278 " typedef enum {\n",
00279 (*i).getComment().c_str());
00280 vector< pair<string,string> > items = (*i).getItems();
00281 vector< pair<string,string> >::iterator j = items.begin();
00282 while (j != items.end()) {
00283 fprintf(f, " %s /**< %s */", (*j).first.c_str(), (*j).second.c_str());
00284 ++j;
00285 if ( j != items.end() ) {
00286 fprintf(f, ",\n");
00287 } else {
00288 fprintf(f, "\n");
00289 }
00290 }
00291 fprintf(f, " } %s;\n\n", (*i).getName().c_str());
00292 }
00293 }
00294
00295
00296
00297
00298
00299 void
00300 CppInterfaceGenerator::write_messages_h(FILE *f)
00301 {
00302 fprintf(f, " /* messages */\n");
00303 for (vector<InterfaceMessage>::iterator i = messages.begin(); i != messages.end(); ++i) {
00304 fprintf(f, " class %s : public Message\n"
00305 " {\n", (*i).getName().c_str());
00306
00307 if (i->getFields().size() > 0) {
00308 fprintf(f, " private:\n");
00309 write_struct(f, (*i).getName() + "_data_t", " ", (*i).getFields());
00310 fprintf(f,
00311 " %s_data_t *data;\n\n",
00312 (*i).getName().c_str());
00313 }
00314
00315 fprintf(f, " public:\n");
00316 write_message_ctor_dtor_h(f, " ", (*i).getName(), (*i).getFields());
00317 write_methods_h(f, " ", (*i).getFields());
00318 write_message_clone_method_h(f, " ");
00319 fprintf(f, " };\n\n");
00320 }
00321 fprintf(f, " virtual bool message_valid(const Message *message) const;\n");
00322
00323 }
00324
00325
00326
00327
00328
00329 void
00330 CppInterfaceGenerator::write_messages_cpp(FILE *f)
00331 {
00332 fprintf(f, "/* =========== messages =========== */\n");
00333 for (vector<InterfaceMessage>::iterator i = messages.begin(); i != messages.end(); ++i) {
00334 fprintf(f,
00335 "/** @class %s::%s <interfaces/%s>\n"
00336 " * %s Fawkes BlackBoard Interface Message.\n"
00337 " * %s\n"
00338 " */\n\n\n",
00339 class_name.c_str(), (*i).getName().c_str(), filename_h.c_str(),
00340 (*i).getName().c_str(), (*i).getComment().c_str());
00341
00342 write_message_ctor_dtor_cpp(f, (*i).getName(), "Message", class_name + "::",
00343 (*i).getFields());
00344 write_methods_cpp(f, class_name, (*i).getName(), (*i).getFields(), class_name + "::");
00345 write_message_clone_method_cpp(f, (class_name + "::" + (*i).getName()).c_str());
00346 }
00347 fprintf(f,
00348 "/** Check if message is valid and can be enqueued.\n"
00349 " * @param message Message to check\n"
00350 " */\n"
00351 "bool\n"
00352 "%s::message_valid(const Message *message) const\n"
00353 "{\n", class_name.c_str());
00354 unsigned int n = 0;
00355 for (vector<InterfaceMessage>::iterator i = messages.begin(); i != messages.end(); ++i) {
00356 fprintf(f,
00357 " const %s *m%u = dynamic_cast<const %s *>(message);\n"
00358 " if ( m%u != NULL ) {\n"
00359 " return true;\n"
00360 " }\n",
00361 (*i).getName().c_str(), n, (*i).getName().c_str(), n);
00362 ++n;
00363 }
00364 fprintf(f,
00365 " return false;\n"
00366 "}\n\n");
00367 }
00368
00369
00370
00371
00372
00373 void
00374 CppInterfaceGenerator::write_create_message_method_cpp(FILE *f)
00375 {
00376 fprintf(f, "/* =========== message create =========== */\n");
00377 fprintf(f,
00378 "Message *\n"
00379 "%s::create_message(const char *type) const\n"
00380 "{\n", class_name.c_str());
00381
00382 bool first = true;
00383 for (vector<InterfaceMessage>::iterator i = messages.begin(); i != messages.end(); ++i) {
00384 fprintf(f,
00385 " %sif ( strncmp(\"%s\", type, __INTERFACE_MESSAGE_TYPE_SIZE) == 0 ) {\n"
00386 " return new %s();\n",
00387 first ? "" : "} else ", i->getName().c_str(), i->getName().c_str());
00388 first = false;
00389 }
00390 if (first) {
00391 fprintf(f,
00392 " throw UnknownTypeException(\"The given type '%%s' does not match any known \"\n"
00393 " \"message type for this interface type.\", type);\n"
00394 "}\n\n\n");
00395 } else {
00396 fprintf(f,
00397 " } else {\n"
00398 " throw UnknownTypeException(\"The given type '%%s' does not match any known \"\n"
00399 " \"message type for this interface type.\", type);\n"
00400 " }\n"
00401 "}\n\n\n");
00402 }
00403 }
00404
00405
00406
00407
00408
00409 void
00410 CppInterfaceGenerator::write_copy_value_method_cpp(FILE *f)
00411 {
00412 fprintf(f,
00413 "/** Copy values from other interface.\n"
00414 " * @param other other interface to copy values from\n"
00415 " */\n"
00416 "void\n"
00417 "%s::copy_values(const Interface *other)\n"
00418 "{\n"
00419 " const %s *oi = dynamic_cast<const %s *>(other);\n"
00420 " if (oi == NULL) {\n"
00421 " throw TypeMismatchException(\"Can only copy values from interface of same type (%%s vs. %%s)\",\n"
00422 " type(), other->type());\n"
00423 " }\n"
00424 " memcpy(data, oi->data, sizeof(%s_data_t));\n"
00425 "}\n\n",
00426 class_name.c_str(), class_name.c_str(), class_name.c_str(), class_name.c_str());
00427 }
00428
00429
00430
00431
00432
00433 void
00434 CppInterfaceGenerator::write_basemethods_cpp(FILE *f)
00435 {
00436 write_create_message_method_cpp(f);
00437 write_copy_value_method_cpp(f);
00438 }
00439
00440
00441
00442
00443
00444
00445
00446 void
00447 CppInterfaceGenerator::write_ctor_dtor_h(FILE *f, std::string is,
00448 std::string classname)
00449 {
00450 fprintf(f,
00451 "%s%s();\n"
00452 "%s~%s();\n\n",
00453 is.c_str(), classname.c_str(),
00454 is.c_str(), classname.c_str());
00455 }
00456
00457
00458
00459
00460
00461
00462
00463
00464 void
00465 CppInterfaceGenerator::write_message_ctor_dtor_h(FILE *f, std::string is,
00466 std::string classname,
00467 std::vector<InterfaceField> fields)
00468 {
00469 vector<InterfaceField>::iterator i;
00470
00471 if ( fields.size() > 0 ) {
00472
00473 fprintf(f, "%s%s(", is.c_str(), classname.c_str());
00474
00475 i = fields.begin();
00476 while (i != fields.end()) {
00477 fprintf(f, "const %s ini_%s",
00478 (*i).getAccessType().c_str(), (*i).getName().c_str());
00479 ++i;
00480 if ( i != fields.end() ) {
00481 fprintf(f, ", ");
00482 }
00483 }
00484
00485 fprintf(f, ");\n");
00486 }
00487
00488 write_ctor_dtor_h(f, is, classname);
00489 fprintf(f, "%s%s(const %s *m);\n", is.c_str(), classname.c_str(), classname.c_str());
00490
00491 }
00492
00493
00494
00495
00496
00497
00498 void
00499 CppInterfaceGenerator::write_message_clone_method_h(FILE *f, std::string is)
00500 {
00501 fprintf(f, "%svirtual Message * clone() const;\n", is.c_str());
00502 }
00503
00504
00505
00506
00507
00508
00509 void
00510 CppInterfaceGenerator::write_message_clone_method_cpp(FILE *f, std::string classname)
00511 {
00512 fprintf(f,
00513 "/** Clone this message.\n"
00514 " * Produces a message of the same type as this message and copies the\n"
00515 " * data to the new message.\n"
00516 " * @return clone of this message\n"
00517 " */\n"
00518 "Message *\n"
00519 "%s::clone() const\n"
00520 "{\n"
00521 " return new %s(this);\n"
00522 "}\n", classname.c_str(), classname.c_str());
00523 }
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534 void
00535 CppInterfaceGenerator::write_ctor_dtor_cpp(FILE *f,
00536 std::string classname, std::string super_class,
00537 std::string inclusion_prefix,
00538 std::vector<InterfaceField> fields,
00539 std::vector<InterfaceMessage> messages)
00540 {
00541 fprintf(f,
00542 "/** Constructor */\n"
00543 "%s%s::%s() : %s()\n"
00544 "{\n",
00545 inclusion_prefix.c_str(), classname.c_str(),
00546 classname.c_str(), super_class.c_str());
00547
00548 if ( fields.size() > 0 ) {
00549 fprintf(f,
00550 " data_size = sizeof(%s_data_t);\n"
00551 " data_ptr = malloc(data_size);\n"
00552 " data = (%s_data_t *)data_ptr;\n"
00553 " memset(data_ptr, 0, data_size);\n",
00554 classname.c_str(), classname.c_str());
00555
00556
00557 for (vector<InterfaceField>::iterator i = fields.begin(); i != fields.end(); ++i) {
00558 const char *type = "";
00559 const char *dataptr = "&";
00560 bool do_print = true;
00561
00562 if ( i->getType() == "bool" ) {
00563 type = "BOOL";
00564 } else if ( i->getType() == "int" ) {
00565 type = "INT";
00566 } else if ( i->getType() == "unsigned int" ) {
00567 type = "UINT";
00568 } else if ( i->getType() == "byte" ) {
00569 type = "BYTE";
00570 } else if ( i->getType() == "long int" ) {
00571 type = "LONGINT";
00572 } else if ( i->getType() == "unsigned long int" ) {
00573 type = "LONGUINT";
00574 } else if ( i->getType() == "float" ) {
00575 type = "FLOAT";
00576 } else if ( i->getType() == "string" ) {
00577 type = "STRING";
00578 dataptr = "";
00579 } else {
00580 do_print = false;
00581 }
00582
00583 if (do_print) {
00584 fprintf(f, " add_fieldinfo(IFT_%s, \"%s\", %u, %sdata->%s);\n",
00585 type, i->getName().c_str(),
00586 (i->getLengthValue() > 0) ? i->getLengthValue() : 1,
00587 dataptr, i->getName().c_str());
00588 }
00589 }
00590 } else {
00591 fprintf(f,
00592 " data_size = 0;\n"
00593 " data_ptr = NULL;\n");
00594 }
00595
00596 for (vector<InterfaceMessage>::iterator i = messages.begin(); i != messages.end(); ++i) {
00597 fprintf(f, " add_messageinfo(\"%s\");\n", i->getName().c_str());
00598 }
00599
00600 fprintf(f, " unsigned char tmp_hash[] = {");
00601 for (size_t st = 0; st < hash_size-1; ++st) {
00602 fprintf(f, "%#02x, ", hash[st]);
00603 }
00604 fprintf(f, "%#02x};\n", hash[hash_size-1]);
00605 fprintf(f, " set_hash(tmp_hash);\n");
00606
00607 fprintf(f,
00608 "}\n\n"
00609 "/** Destructor */\n"
00610 "%s%s::~%s()\n"
00611 "{\n"
00612 " free(data_ptr);\n"
00613 "}\n",
00614 inclusion_prefix.c_str(), classname.c_str(), classname.c_str()
00615 );
00616 }
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626 void
00627 CppInterfaceGenerator::write_message_ctor_dtor_cpp(FILE *f,
00628 std::string classname, std::string super_class,
00629 std::string inclusion_prefix,
00630 std::vector<InterfaceField> fields)
00631 {
00632 vector<InterfaceField>::iterator i;
00633
00634 if ( fields.size() > 0 ) {
00635 fprintf(f,
00636 "/** Constructor with initial values.\n");
00637
00638 for (i = fields.begin(); i != fields.end(); ++i) {
00639 fprintf(f, " * @param ini_%s initial value for %s\n",
00640 (*i).getName().c_str(), (*i).getName().c_str());
00641 }
00642
00643 fprintf(f,
00644 " */\n"
00645 "%s%s::%s(",
00646 inclusion_prefix.c_str(), classname.c_str(), classname.c_str());
00647
00648 i = fields.begin();
00649 while (i != fields.end()) {
00650 fprintf(f, "const %s ini_%s",
00651 (*i).getAccessType().c_str(), (*i).getName().c_str());
00652 ++i;
00653 if ( i != fields.end() ) {
00654 fprintf(f, ", ");
00655 }
00656 }
00657
00658 fprintf(f,") : %s(\"%s\")\n"
00659 "{\n"
00660 " data_size = sizeof(%s_data_t);\n"
00661 " data_ptr = malloc(data_size);\n"
00662 " memset(data_ptr, 0, data_size);\n"
00663 " data = (%s_data_t *)data_ptr;\n",
00664 super_class.c_str(), classname.c_str(), classname.c_str(), classname.c_str());
00665
00666 for (i = fields.begin(); i != fields.end(); ++i) {
00667 if ( (*i).getType() == "string" ) {
00668 fprintf(f, " strncpy(data->%s, ini_%s, %s);\n",
00669 (*i).getName().c_str(), (*i).getName().c_str(),
00670 (*i).getLength().c_str());
00671 } else if (i->getLengthValue() > 1) {
00672 fprintf(f, " memcpy(data->%s, ini_%s, sizeof(%s) * %s);\n",
00673 i->getName().c_str(), i->getName().c_str(),
00674 i->getPlainAccessType().c_str(), i->getLength().c_str());
00675
00676
00677 } else {
00678 fprintf(f, " data->%s = ini_%s;\n",
00679 (*i).getName().c_str(), (*i).getName().c_str());
00680 }
00681 }
00682
00683 for (i = fields.begin(); i != fields.end(); ++i) {
00684 const char *type = "";
00685 const char *dataptr = "&";
00686 bool do_print = true;
00687
00688 if ( i->getType() == "bool" ) {
00689 type = "BOOL";
00690 } else if ( i->getType() == "int" ) {
00691 type = "INT";
00692 } else if ( i->getType() == "unsigned int" ) {
00693 type = "UINT";
00694 } else if ( i->getType() == "byte" ) {
00695 type = "BYTE";
00696 } else if ( i->getType() == "long int" ) {
00697 type = "LONGINT";
00698 } else if ( i->getType() == "unsigned long int" ) {
00699 type = "LONGUINT";
00700 } else if ( i->getType() == "float" ) {
00701 type = "FLOAT";
00702 } else if ( i->getType() == "string" ) {
00703 type = "STRING";
00704 dataptr = "";
00705 } else {
00706 do_print = false;
00707 }
00708
00709 if (do_print) {
00710 fprintf(f, " add_fieldinfo(IFT_%s, \"%s\", %u, %sdata->%s);\n",
00711 type, i->getName().c_str(),
00712 (i->getLengthValue() > 0) ? i->getLengthValue() : 1,
00713 dataptr, i->getName().c_str());
00714 }
00715 }
00716
00717 fprintf(f, "}\n");
00718 }
00719
00720 fprintf(f,
00721 "/** Constructor */\n"
00722 "%s%s::%s() : %s(\"%s\")\n"
00723 "{\n",
00724 inclusion_prefix.c_str(), classname.c_str(),
00725 classname.c_str(), super_class.c_str(), classname.c_str());
00726
00727 if ( fields.size() > 0 ) {
00728 fprintf(f,
00729 " data_size = sizeof(%s_data_t);\n"
00730 " data_ptr = malloc(data_size);\n"
00731 " memset(data_ptr, 0, data_size);\n"
00732 " data = (%s_data_t *)data_ptr;\n",
00733 classname.c_str(), classname.c_str());
00734
00735 for (i = fields.begin(); i != fields.end(); ++i) {
00736 const char *type = "";
00737 const char *dataptr = "&";
00738 bool do_print = true;
00739
00740 if ( i->getType() == "bool" ) {
00741 type = "BOOL";
00742 } else if ( i->getType() == "int" ) {
00743 type = "INT";
00744 } else if ( i->getType() == "unsigned int" ) {
00745 type = "UINT";
00746 } else if ( i->getType() == "byte" ) {
00747 type = "BYTE";
00748 } else if ( i->getType() == "long int" ) {
00749 type = "LONGINT";
00750 } else if ( i->getType() == "unsigned long int" ) {
00751 type = "LONGUINT";
00752 } else if ( i->getType() == "float" ) {
00753 type = "FLOAT";
00754 } else if ( i->getType() == "string" ) {
00755 type = "STRING";
00756 dataptr = "";
00757 } else {
00758 do_print = false;
00759 }
00760
00761 if (do_print) {
00762 fprintf(f, " add_fieldinfo(IFT_%s, \"%s\", %u, %sdata->%s);\n",
00763 type, i->getName().c_str(),
00764 (i->getLengthValue() > 0) ? i->getLengthValue() : 1,
00765 dataptr, i->getName().c_str());
00766 }
00767 }
00768
00769 } else {
00770 fprintf(f,
00771 " data_size = 0;\n"
00772 " data_ptr = NULL;\n");
00773 }
00774
00775 fprintf(f,
00776 "}\n\n"
00777 "/** Destructor */\n"
00778 "%s%s::~%s()\n"
00779 "{\n"
00780 "%s"
00781 "}\n\n",
00782 inclusion_prefix.c_str(), classname.c_str(), classname.c_str(),
00783 (fields.size() > 0) ? " free(data_ptr);\n" : ""
00784 );
00785
00786 fprintf(f,
00787 "/** Copy constructor.\n"
00788 " * @param m message to copy from\n"
00789 " */\n"
00790 "%s%s::%s(const %s *m) : %s(\"%s\")\n"
00791 "{\n",
00792 inclusion_prefix.c_str(), classname.c_str(), classname.c_str(),
00793 classname.c_str(), super_class.c_str(), classname.c_str());
00794
00795 if ( fields.size() > 0 ) {
00796 fprintf(f,
00797 " data_size = m->data_size;\n"
00798 " data_ptr = malloc(data_size);\n"
00799 " memcpy(data_ptr, m->data_ptr, data_size);\n"
00800 " data = (%s_data_t *)data_ptr;\n", classname.c_str());
00801 } else {
00802 fprintf(f,
00803 " data_size = 0;\n"
00804 " data_ptr = NULL;\n");
00805 }
00806
00807 fprintf(f, "}\n\n");
00808 }
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818 void
00819 CppInterfaceGenerator::write_methods_cpp(FILE *f, std::string interface_classname,
00820 std::string classname,
00821 std::vector<InterfaceField> fields,
00822 std::string inclusion_prefix)
00823 {
00824 fprintf(f, "/* Methods */\n");
00825 for (vector<InterfaceField>::iterator i = fields.begin(); i != fields.end(); ++i) {
00826 fprintf(f,
00827 "/** Get %s value.\n"
00828 " * %s\n"
00829 " * @return %s value\n"
00830 " */\n"
00831 "%s%s\n"
00832 "%s%s::%s%s() const\n"
00833 "{\n"
00834 " return data->%s;\n"
00835 "}\n\n",
00836 (*i).getName().c_str(),
00837 (*i).getComment().c_str(),
00838 (*i).getName().c_str(),
00839 (*i).isEnumType() ? (interface_classname + "::").c_str() : "",
00840 (*i).getAccessType().c_str(),
00841 inclusion_prefix.c_str(), classname.c_str(), ( ((*i).getType() == "bool" ) ? "is_" : ""), (*i).getName().c_str(),
00842 (*i).getName().c_str() );
00843
00844 if ( (i->getLengthValue() > 0) && (i->getType() != "string") ) {
00845 fprintf(f,
00846 "/** Get %s value at given index.\n"
00847 " * %s\n"
00848 " * @param index index of value\n"
00849 " * @return %s value\n"
00850 " * @exception Exception thrown if index is out of bounds\n"
00851 " */\n"
00852 "%s%s\n"
00853 "%s%s::%s%s(unsigned int index) const\n"
00854 "{\n"
00855 " if (index > %s) {\n"
00856 " throw Exception(\"Index value %%u out of bounds (0..%s)\", index);\n"
00857 " }\n"
00858 " return data->%s[index];\n"
00859 "}\n\n",
00860 (*i).getName().c_str(),
00861 (*i).getComment().c_str(),
00862 (*i).getName().c_str(),
00863 (*i).isEnumType() ? (interface_classname + "::").c_str() : "",
00864 (*i).getPlainAccessType().c_str(),
00865 inclusion_prefix.c_str(), classname.c_str(),
00866 ( ((*i).getType() == "bool" ) ? "is_" : ""), (*i).getName().c_str(),
00867 i->getLength().c_str(), i->getLength().c_str(),
00868 (*i).getName().c_str() );
00869 }
00870
00871 fprintf(f,
00872 "/** Get maximum length of %s value.\n"
00873 " * @return length of %s value, can be length of the array or number of \n"
00874 " * maximum number of characters for a string\n"
00875 " */\n"
00876 "size_t\n"
00877 "%s%s::maxlenof_%s() const\n"
00878 "{\n"
00879 " return %s;\n"
00880 "}\n\n",
00881 i->getName().c_str(), i->getName().c_str(), inclusion_prefix.c_str(),
00882 classname.c_str(), i->getName().c_str(),
00883 i->getLengthValue() > 0 ? i->getLength().c_str() : "1" );
00884
00885 fprintf(f,
00886 "/** Set %s value.\n"
00887 " * %s\n"
00888 " * @param new_%s new %s value\n"
00889 " */\n"
00890 "void\n"
00891 "%s%s::set_%s(const %s new_%s)\n"
00892 "{\n",
00893 (*i).getName().c_str(),
00894 (*i).getComment().c_str(),
00895 (*i).getName().c_str(), (*i).getName().c_str(),
00896 inclusion_prefix.c_str(), classname.c_str(), (*i).getName().c_str(), (*i).getAccessType().c_str(), (*i).getName().c_str()
00897 );
00898 if ( (*i).getType() == "string" ) {
00899 fprintf(f,
00900 " strncpy(data->%s, new_%s, sizeof(data->%s));\n",
00901 (*i).getName().c_str(), (*i).getName().c_str(), (*i).getName().c_str());
00902 } else if ( (*i).getLength() != "" ) {
00903 fprintf(f,
00904 " memcpy(data->%s, new_%s, sizeof(%s) * %s);\n",
00905 (*i).getName().c_str(), (*i).getName().c_str(),
00906 (*i).getPlainAccessType().c_str(), (*i).getLength().c_str());
00907 } else {
00908 fprintf(f,
00909 " data->%s = new_%s;\n",
00910 (*i).getName().c_str(), (*i).getName().c_str());
00911 }
00912 fprintf(f, "}\n\n");
00913
00914 if ( ((*i).getType() != "string") && ((*i).getLengthValue() > 0) ) {
00915 fprintf(f,
00916 "/** Set %s value at given index.\n"
00917 " * %s\n"
00918 " * @param new_%s new %s value\n"
00919 " * @param index index for of the value\n"
00920 " */\n"
00921 "void\n"
00922 "%s%s::set_%s(unsigned int index, const %s new_%s)\n"
00923 "{\n"
00924 " if (index > %s) {\n"
00925 " throw Exception(\"Index value %%u out of bounds (0..%s)\", index);\n"
00926 " }\n"
00927 " data->%s[index] = new_%s;\n"
00928 "}\n",
00929 (*i).getName().c_str(),
00930 (*i).getComment().c_str(),
00931 (*i).getName().c_str(), (*i).getName().c_str(),
00932 inclusion_prefix.c_str(), classname.c_str(), (*i).getName().c_str(),
00933 (*i).getPlainAccessType().c_str(), i->getName().c_str(),
00934 i->getLength().c_str(), i->getLength().c_str(),
00935 i->getName().c_str(), i->getName().c_str());
00936 }
00937 }
00938 }
00939
00940
00941
00942
00943
00944
00945
00946
00947
00948
00949 void
00950 CppInterfaceGenerator::write_methods_cpp(FILE *f, std::string interface_classname,
00951 std::string classname,
00952 std::vector<InterfaceField> fields,
00953 std::vector<InterfacePseudoMap> pseudo_maps,
00954 std::string inclusion_prefix)
00955 {
00956 write_methods_cpp(f, interface_classname, classname, fields, inclusion_prefix);
00957
00958 for (vector<InterfacePseudoMap>::iterator i = pseudo_maps.begin(); i != pseudo_maps.end(); ++i) {
00959 fprintf(f,
00960 "/** Get %s value.\n"
00961 " * %s\n"
00962 " * @param key key of the value\n"
00963 " * @return %s value\n"
00964 " */\n"
00965 "%s\n"
00966 "%s%s::%s(const %s key) const\n"
00967 "{\n",
00968 (*i).getName().c_str(),
00969 (*i).getComment().c_str(),
00970 (*i).getName().c_str(),
00971 (*i).getType().c_str(),
00972 inclusion_prefix.c_str(), classname.c_str(), (*i).getName().c_str(),
00973 (*i).getKeyType().c_str() );
00974
00975 InterfacePseudoMap::RefList &reflist = i->getRefList();
00976 InterfacePseudoMap::RefList::iterator paref;
00977 bool first = true;
00978 for (paref = reflist.begin(); paref != reflist.end(); ++paref) {
00979 fprintf(f, " %sif (key == %s) {\n"
00980 " return data->%s;\n",
00981 first ? "" : "} else ",
00982 paref->second.c_str(), paref->first.c_str());
00983 first = false;
00984 }
00985 fprintf(f, " } else {\n"
00986 " throw Exception(\"Invalid key, cannot retrieve value\");\n"
00987 " }\n"
00988 "}\n\n");
00989
00990 fprintf(f,
00991 "/** Set %s value.\n"
00992 " * %s\n"
00993 " * @param key key of the value\n"
00994 " * @param new_value new value\n"
00995 " */\n"
00996 "void\n"
00997 "%s%s::set_%s(const %s key, const %s new_value)\n"
00998 "{\n",
00999 (*i).getName().c_str(),
01000 (*i).getComment().c_str(),
01001 inclusion_prefix.c_str(), classname.c_str(), (*i).getName().c_str(),
01002 (*i).getKeyType().c_str(), (*i).getType().c_str());
01003
01004 first = true;
01005 for (paref = reflist.begin(); paref != reflist.end(); ++paref) {
01006 fprintf(f, " %sif (key == %s) {\n"
01007 " data->%s = new_value;\n",
01008 first ? "" : "} else ",
01009 paref->second.c_str(), paref->first.c_str());
01010 first = false;
01011 }
01012
01013 fprintf(f, " }\n"
01014 "}\n\n");
01015 }
01016 }
01017
01018
01019
01020
01021
01022
01023
01024
01025 void
01026 CppInterfaceGenerator::write_methods_h(FILE *f, std::string is,
01027 std::vector<InterfaceField> fields)
01028 {
01029 fprintf(f, "%s/* Methods */\n", is.c_str());
01030 for (vector<InterfaceField>::iterator i = fields.begin(); i != fields.end(); ++i) {
01031 fprintf(f,
01032 "%s%s %s%s() const;\n",
01033 is.c_str(), (*i).getAccessType().c_str(),
01034 ( ((*i).getType() == "bool" ) ? "is_" : ""),
01035 (*i).getName().c_str());
01036
01037 if ((i->getLengthValue() > 0) && (i->getType() != "string")) {
01038 fprintf(f,
01039 "%s%s %s%s(unsigned int index) const;\n"
01040 "%svoid set_%s(unsigned int index, const %s new_%s);\n",
01041 is.c_str(), i->getPlainAccessType().c_str(),
01042 ( ((*i).getType() == "bool" ) ? "is_" : ""),
01043 (*i).getName().c_str(),
01044 is.c_str(), (*i).getName().c_str(),
01045 i->getPlainAccessType().c_str(), i->getName().c_str());
01046 }
01047
01048 fprintf(f,
01049 "%svoid set_%s(const %s new_%s);\n"
01050 "%ssize_t maxlenof_%s() const;\n",
01051 is.c_str(), (*i).getName().c_str(),
01052 i->getAccessType().c_str(), i->getName().c_str(),
01053 is.c_str(), i->getName().c_str()
01054 );
01055 }
01056 }
01057
01058
01059
01060
01061
01062
01063
01064
01065 void
01066 CppInterfaceGenerator::write_methods_h(FILE *f, std::string is,
01067 std::vector<InterfaceField> fields,
01068 std::vector<InterfacePseudoMap> pseudo_maps)
01069 {
01070 write_methods_h(f, is, fields);
01071
01072 for (vector<InterfacePseudoMap>::iterator i = pseudo_maps.begin(); i != pseudo_maps.end(); ++i) {
01073 fprintf(f,
01074 "%s%s %s(%s key) const;\n"
01075 "%svoid set_%s(const %s key, const %s new_value);\n",
01076 is.c_str(), (*i).getType().c_str(),
01077 (*i).getName().c_str(), (*i).getKeyType().c_str(),
01078 is.c_str(), (*i).getName().c_str(),
01079 i->getKeyType().c_str(), i->getType().c_str());
01080 }
01081 }
01082
01083
01084
01085
01086
01087
01088 void
01089 CppInterfaceGenerator::write_basemethods_h(FILE *f, std::string is)
01090 {
01091 fprintf(f,
01092 "%svirtual Message * create_message(const char *type) const;\n\n"
01093 "%svirtual void copy_values(const Interface *other);\n",
01094 is.c_str(), is.c_str());
01095 }
01096
01097
01098
01099
01100 void
01101 CppInterfaceGenerator::write_h(FILE *f)
01102 {
01103 write_header(f, filename_h);
01104 write_deflector(f);
01105
01106 fprintf(f,
01107 "#include <interface/interface.h>\n"
01108 "#include <interface/message.h>\n"
01109 "#include <interface/field_iterator.h>\n\n"
01110 "namespace fawkes {\n\n"
01111 "class %s : public Interface\n"
01112 "{\n"
01113 " /// @cond INTERNALS\n"
01114 " INTERFACE_MGMT_FRIENDS(%s)\n"
01115 " /// @endcond\n"
01116 " public:\n",
01117 class_name.c_str(),
01118 class_name.c_str());
01119
01120 write_constants_h(f);
01121
01122 fprintf(f, " private:\n");
01123
01124 write_struct(f, class_name + "_data_t", " ", data_fields);
01125
01126 fprintf(f, " %s_data_t *data;\n"
01127 "\n public:\n", class_name.c_str());
01128
01129 write_messages_h(f);
01130 fprintf(f, " private:\n");
01131 write_ctor_dtor_h(f, " ", class_name);
01132 fprintf(f, " public:\n");
01133 write_methods_h(f, " ", data_fields, pseudo_maps);
01134 write_basemethods_h(f, " ");
01135 fprintf(f, "\n};\n\n} // end namespace fawkes\n\n#endif\n");
01136 }
01137
01138
01139
01140
01141 void
01142 CppInterfaceGenerator::generate()
01143 {
01144 char timestring[26];
01145 struct tm timestruct;
01146 time_t t = time(NULL);
01147 localtime_r(&t, ×truct);
01148 asctime_r(×truct, timestring);
01149 gendate = timestring;
01150
01151 FILE *cpp;
01152 FILE *h;
01153
01154 cpp = fopen(string(dir + filename_cpp).c_str(), "w");
01155 h = fopen(string(dir + filename_h).c_str(), "w");
01156
01157 if ( cpp == NULL ) {
01158 printf("Cannot open cpp file %s%s\n", dir.c_str(), filename_cpp.c_str());
01159 }
01160 if ( h == NULL ) {
01161 printf("Cannot open h file %s%s\n", dir.c_str(), filename_h.c_str());
01162 }
01163
01164 write_cpp(cpp);
01165 write_h(h);
01166
01167 fclose(cpp);
01168 fclose(h);
01169 }