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