ts_generator.cpp

Go to the documentation of this file.
00001 /*
00002  *
00003  *
00004  * Distributed under the OpenDDS License.
00005  * See: http://www.opendds.org/license.html
00006  */
00007 
00008 #include "ts_generator.h"
00009 #include "be_extern.h"
00010 
00011 #include "utl_identifier.h"
00012 
00013 #include "ace/OS_NS_sys_stat.h"
00014 
00015 #include <cstring>
00016 #include <fstream>
00017 #include <sstream>
00018 #include <map>
00019 #include <iostream>
00020 
00021 namespace {
00022   std::string read_template(const char* prefix)
00023   {
00024     const char* dds_root = ACE_OS::getenv("DDS_ROOT");
00025     if (!dds_root) {
00026       ACE_DEBUG((LM_ERROR, "The environment variable DDS_ROOT must be set.\n"));
00027       BE_abort();
00028     }
00029     std::string path = dds_root;
00030     path.append("/dds/idl/");
00031     path.append(prefix);
00032     path.append("Template.txt");
00033     std::ifstream ifs(path.c_str());
00034     std::ostringstream oss;
00035     oss << ifs.rdbuf();
00036     return oss.str();
00037   }
00038 
00039   void replaceAll(std::string& s,
00040                   const std::map<std::string, std::string>& rep) {
00041     typedef std::map<std::string, std::string>::const_iterator mapiter_t;
00042     for (size_t i = s.find("<%"); i < s.length(); i = s.find("<%", i + 1)) {
00043       size_t n = s.find("%>", i) - i + 2;
00044       mapiter_t iter = rep.find(s.substr(i + 2, n - 4));
00045       if (iter != rep.end()) {
00046         s.replace(i, n, iter->second);
00047       }
00048     }
00049   }
00050 
00051   template<size_t N>
00052   void add_includes(const char* (&includes)[N],
00053                     BE_GlobalData::stream_enum_t whichStream) {
00054     for (size_t i = 0; i < N; ++i) {
00055       be_global->add_include(includes[i], whichStream);
00056     }
00057   }
00058 
00059 }
00060 
00061 ts_generator::ts_generator()
00062   : idl_template_(read_template("IDL"))
00063 {
00064 }
00065 
00066 bool ts_generator::gen_struct(AST_Structure*, UTL_ScopedName* name,
00067   const std::vector<AST_Field*>&, AST_Type::SIZE_TYPE, const char*)
00068 {
00069   if (idl_global->is_dcps_type(name) == 0) {
00070     // no #pragma DCPS_DATA_TYPE, so nothing to generate
00071     return true;
00072   }
00073 
00074   const std::string cxxName = scoped(name);
00075   const std::string short_name = name->last_component()->get_string();
00076 
00077   static const char* idl_includes[] = {
00078     "dds/DdsDcpsInfrastructure.idl", "dds/DdsDcpsTopic.idl",
00079     "dds/DdsDcpsPublication.idl", "dds/DdsDcpsSubscriptionExt.idl",
00080     "dds/DdsDcpsTypeSupportExt.idl"
00081   };
00082   add_includes(idl_includes, BE_GlobalData::STREAM_IDL);
00083 
00084   std::string dc = be_global->header_name_.c_str();
00085   dc.replace(dc.end() - 6, dc.end() - 2, "C"); // s/Impl.h$/C.h/
00086   be_global->add_include(dc.c_str());
00087 
00088   static const char* h_includes[] = {
00089     "dds/DCPS/DataWriterImpl_T.h",
00090     "dds/DCPS/DataReaderImpl_T.h",
00091     "dds/DCPS/TypeSupportImpl_T.h"
00092   };
00093   add_includes(h_includes, BE_GlobalData::STREAM_H);
00094 
00095   static const char* cpp_includes[] = {
00096     "dds/DCPS/debug.h", "dds/DCPS/Registered_Data_Types.h",
00097     "dds/DdsDcpsDomainC.h", "dds/DCPS/Service_Participant.h",
00098     "dds/DCPS/Qos_Helper.h", "dds/DCPS/PublicationInstance.h",
00099     "dds/DCPS/PublisherImpl.h", "dds/DCPS/SubscriberImpl.h",
00100     "dds/DCPS/ReceivedDataElementList.h", "dds/DCPS/RakeResults_T.h",
00101     "dds/DCPS/BuiltInTopicUtils.h", "dds/DCPS/Util.h",
00102     "dds/DCPS/ContentFilteredTopicImpl.h", "dds/DCPS/RakeData.h",
00103     "dds/DCPS/MultiTopicDataReader_T.h"
00104   };
00105   add_includes(cpp_includes, BE_GlobalData::STREAM_CPP);
00106 
00107   std::map<std::string, std::string> replacements;
00108   replacements["SCOPED"] = cxxName;
00109   replacements["TYPE"] = short_name;
00110   replacements["EXPORT"] = be_global->export_macro().c_str();
00111   replacements["SEQ"] = be_global->sequence_suffix().c_str();
00112 
00113   ScopedNamespaceGuard idlGuard(name, be_global->idl_, "module");
00114   std::string idl = idl_template_;
00115   replaceAll(idl, replacements);
00116   be_global->idl_ << idl;
00117 
00118   be_global->header_ <<
00119     "namespace OpenDDS { namespace DCPS {\n"
00120     "template <>\n"
00121     "struct DDSTraits<" << cxxName << "> {\n"
00122     "  typedef " << cxxName << " MessageType;\n"
00123     "  typedef " << cxxName << "Seq MessageSequenceType;\n"
00124     "  typedef " << cxxName << "TypeSupport TypeSupportType;\n"
00125     "  typedef " << cxxName << "DataWriter DataWriterType;\n"
00126     "  typedef " << cxxName << "DataReader DataReaderType;\n"
00127     "  typedef " << module_scope(name) << "OpenDDSGenerated::" << short_name << "_KeyLessThan LessThanType;\n"
00128     "\n"
00129     "  inline static const char* type_name () { return \"" << cxxName << "\"; }\n"
00130     "  inline static bool gen_has_key (const MessageType& x) { return ::OpenDDS::DCPS::gen_has_key(x); }\n"
00131     "\n"
00132     "  inline static bool gen_is_bounded_size (const MessageType& x) { return ::OpenDDS::DCPS::gen_is_bounded_size(x); }\n"
00133     "  inline static size_t gen_max_marshaled_size(const MessageType& x, bool align) { return ::OpenDDS::DCPS::gen_max_marshaled_size(x, align); }\n"
00134     "  inline static void gen_find_size(const MessageType& arr, size_t& size, size_t& padding) { ::OpenDDS::DCPS::gen_find_size(arr, size, padding); }\n"
00135     "\n"
00136     "  inline static bool gen_is_bounded_size (const OpenDDS::DCPS::KeyOnly<const MessageType>& x) { return ::OpenDDS::DCPS::gen_is_bounded_size(x); }\n"
00137     "  inline static size_t gen_max_marshaled_size(const OpenDDS::DCPS::KeyOnly<const MessageType>& x, bool align) { return ::OpenDDS::DCPS::gen_max_marshaled_size(x, align); }\n"
00138     "  inline static void gen_find_size(const OpenDDS::DCPS::KeyOnly<const MessageType>& arr, size_t& size, size_t& padding) { ::OpenDDS::DCPS::gen_find_size(arr, size, padding); }\n"
00139     "};\n}  }\n\n";
00140 
00141   {
00142     ScopedNamespaceGuard hGuard(name, be_global->header_);
00143     be_global->header_ <<
00144       "  typedef OpenDDS::DCPS::DataWriterImpl_T<" << cxxName << "> " << short_name << "DataWriterImpl;\n"
00145       "  typedef OpenDDS::DCPS::DataReaderImpl_T<" << cxxName << "> " << short_name << "DataReaderImpl;\n"
00146       "  typedef OpenDDS::DCPS::TypeSupportImpl_T<" << cxxName << "> " << short_name << "TypeSupportImpl;\n";
00147   }
00148 
00149   ScopedNamespaceGuard cppGuard(name, be_global->impl_);
00150 
00151   if (be_global->face_ts()) {
00152     face_ts_generator::generate(name);
00153   }
00154 
00155   return true;
00156 }
00157 
00158 bool ts_generator::gen_union(AST_Union*, UTL_ScopedName* name,
00159   const std::vector<AST_UnionBranch*>&, AST_Type*, const char*)
00160 {
00161   if (idl_global->is_dcps_type(name)) {
00162     std::cerr << "ERROR: union " << scoped(name) << " can not be used as a "
00163       "DCPS_DATA_TYPE (only structs can be Topic types)" << std::endl;
00164     return false;
00165   }
00166   return true;
00167 }
00168 
00169 namespace java_ts_generator {
00170 
00171   /// called directly by dds_visitor::visit_structure() if -Wb,java
00172   void generate(UTL_ScopedName* name) {
00173     if (idl_global->is_dcps_type(name) == 0) {
00174       // no #pragma DCPS_DATA_TYPE, so nothing to generate
00175       return;
00176     }
00177 
00178     ACE_CString output_file = be_global->java_arg();
00179     if (output_file.length()) {
00180       be_global->impl_name_ = output_file;
00181     }
00182     be_global->add_include("idl2jni_jni.h", BE_GlobalData::STREAM_CPP);
00183 
00184     std::string type = scoped(name);
00185 
00186     std::string file, jniclass, jpackage;
00187     for (UTL_ScopedName* sn = name; sn;
00188         sn = static_cast<UTL_ScopedName*>(sn->tail())) {
00189       std::string tmp = sn->head()->get_string();
00190       if (tmp != "" && sn->tail()) {
00191         jpackage += tmp;
00192         file += tmp;
00193         ACE_OS::mkdir(file.c_str());
00194       }
00195       for (size_t i = tmp.find('_'); i < tmp.length();
00196           i = tmp.find('_', i + 1)) {
00197         tmp.insert(++i, 1, '1');
00198       }
00199       jniclass += tmp;
00200       if (jniclass != "" && sn->tail()) {
00201         jniclass += '_';
00202         jpackage += '.';
00203         file += '/';
00204       }
00205     }
00206 
00207     if (jpackage[jpackage.size() - 1] == '.') {
00208       jpackage.resize(jpackage.size() - 1);
00209     }
00210 
00211     std::string clazz = name->last_component()->get_string();
00212     file += clazz + "TypeSupportImpl.java";
00213 
00214     std::ofstream java(file.c_str());
00215     java << (jpackage.size() ? "package " : "") << jpackage
00216       << (jpackage.size() ? ";\n" :"") <<
00217       "public class " << clazz << "TypeSupportImpl extends _" << clazz
00218       << "TypeSupportTAOPeer {\n"
00219       "    public " << clazz << "TypeSupportImpl() {\n"
00220       "        super(_jni_init());\n"
00221       "    }\n"
00222       "    private static native long _jni_init();\n"
00223       "}\n";
00224     be_global->impl_ <<
00225       "extern \"C\" JNIEXPORT jlong JNICALL\n"
00226       "Java_" << jniclass << "TypeSupportImpl__1jni_1init(JNIEnv*, jclass) {\n"
00227       "  return reinterpret_cast<jlong>(static_cast<CORBA::Object_ptr>(new "
00228       << type << "TypeSupportImpl));\n"
00229       "}\n\n";
00230   }
00231 
00232 }
00233 
00234 namespace face_ts_generator {
00235 
00236   void generate(UTL_ScopedName* name) {
00237     const std::string name_cxx = scoped(name),
00238       name_underscores = dds_generator::scoped_helper(name, "_"),
00239       exportMacro = be_global->export_macro().c_str(),
00240       exporter = exportMacro.empty() ? "" : ("    " + exportMacro + '\n');
00241     be_global->add_include("FACE/TS.hpp", BE_GlobalData::STREAM_FACETS_H);
00242     be_global->facets_header_ <<
00243       "namespace FACE\n"
00244       "{\n"
00245       "  namespace Read_Callback\n"
00246       "  {\n"
00247       "    typedef void (*send_event_" << name_underscores << "_Ptr) (\n"
00248       "      /* in */ TRANSACTION_ID_TYPE transaction_id,\n"
00249       "      /* inout */ " << name_cxx << "& message,\n"
00250       "      /* in */ MESSAGE_TYPE_GUID message_type_id,\n"
00251       "      /* in */ MESSAGE_SIZE_TYPE message_size,\n"
00252       "      /* in */ const WAITSET_TYPE waitset,\n"
00253       "      /* out */ RETURN_CODE_TYPE& return_code);\n"
00254       "  }\n\n"
00255       "  namespace TS\n"
00256       "  {\n" << exporter <<
00257       "    void Receive_Message(\n"
00258       "      /* in */ CONNECTION_ID_TYPE connection_id,\n"
00259       "      /* in */ TIMEOUT_TYPE timeout,\n"
00260       "      /* inout */ TRANSACTION_ID_TYPE& transaction_id,\n"
00261       "      /* out */ " << name_cxx << "& message,\n"
00262       "      /* in */ MESSAGE_SIZE_TYPE message_size,\n"
00263       "      /* out */ RETURN_CODE_TYPE& return_code);\n\n" << exporter <<
00264       "    void Send_Message(\n"
00265       "      /* in */ CONNECTION_ID_TYPE connection_id,\n"
00266       "      /* in */ TIMEOUT_TYPE timeout,\n"
00267       "      /* inout */ TRANSACTION_ID_TYPE& transaction_id,\n"
00268       "      /* inout */ " << name_cxx << "& message,\n"
00269       "      /* inout */ MESSAGE_SIZE_TYPE& message_size,\n"
00270       "      /* out */ RETURN_CODE_TYPE& return_code);\n\n" << exporter <<
00271       "    void Register_Callback(\n"
00272       "      /* in */ CONNECTION_ID_TYPE connection_id,\n"
00273       "      /* in */ const WAITSET_TYPE waitset,\n"
00274       "      /* in */ Read_Callback::send_event_" << name_underscores
00275                     << "_Ptr data_callback,\n"
00276       "      /* in */ MESSAGE_SIZE_TYPE max_message_size,\n"
00277       "      /* out */ RETURN_CODE_TYPE& return_code);\n\n"
00278       "  }\n"
00279       "}\n\n";
00280     be_global->facets_impl_ <<
00281       "void Receive_Message(CONNECTION_ID_TYPE connection_id,\n"
00282       "                     TIMEOUT_TYPE timeout,\n"
00283       "                     TRANSACTION_ID_TYPE& transaction_id,\n"
00284       "                     " << name_cxx << "& message,\n"
00285       "                     MESSAGE_SIZE_TYPE message_size,\n"
00286       "                     RETURN_CODE_TYPE& return_code) {\n"
00287       "  OpenDDS::FaceTSS::receive_message(connection_id, timeout,\n"
00288       "                                    transaction_id, message,\n"
00289       "                                    message_size, return_code);\n"
00290       "}\n\n"
00291       "void Send_Message(CONNECTION_ID_TYPE connection_id,\n"
00292       "                  TIMEOUT_TYPE timeout,\n"
00293       "                  TRANSACTION_ID_TYPE& transaction_id,\n"
00294       "                  " << name_cxx << "& message,\n"
00295       "                  MESSAGE_SIZE_TYPE& message_size,\n"
00296       "                  RETURN_CODE_TYPE& return_code) {\n"
00297       "  OpenDDS::FaceTSS::send_message(connection_id, timeout,\n"
00298       "                                 transaction_id, message,\n"
00299       "                                 message_size, return_code);\n"
00300       "}\n\n"
00301       "void Register_Callback(CONNECTION_ID_TYPE connection_id,\n"
00302       "                       const WAITSET_TYPE waitset,\n"
00303       "                       Read_Callback::send_event_" << name_underscores
00304                           << "_Ptr data_callback,\n"
00305       "                       MESSAGE_SIZE_TYPE max_message_size,\n"
00306       "                       RETURN_CODE_TYPE& return_code) {\n"
00307       "  OpenDDS::FaceTSS::register_callback(connection_id, waitset,\n"
00308       "                                      data_callback,\n"
00309       "                                      max_message_size, return_code);\n"
00310       "}\n\n"
00311       "struct " << name_underscores << "_Initializer {\n"
00312       "  " << name_underscores << "_Initializer()\n"
00313       "  {\n"
00314       "    " << name_cxx << "TypeSupport_var ts = new " << name_cxx
00315                           << "TypeSupportImpl;\n"
00316       "    ts->register_type(0, \"\");\n"
00317       "  }\n"
00318       "} init_" << name_underscores << ";\n\n";
00319   }
00320 }

Generated on Fri Feb 12 20:05:28 2016 for OpenDDS by  doxygen 1.4.7