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_ERROR((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   IDL_GlobalData::DCPS_Data_Type_Info* info = idl_global->is_dcps_type(name);
00070 
00071   if (!info) {
00072     // no #pragma DCPS_DATA_TYPE, so nothing to generate
00073     return true;
00074   }
00075 
00076   const std::string cxxName = scoped(name);
00077   const std::string short_name = name->last_component()->get_string();
00078 
00079   static const char* idl_includes[] = {
00080     "dds/DdsDcpsInfrastructure.idl", "dds/DdsDcpsTopic.idl",
00081     "dds/DdsDcpsPublication.idl", "dds/DdsDcpsSubscriptionExt.idl",
00082     "dds/DdsDcpsTypeSupportExt.idl"
00083   };
00084   add_includes(idl_includes, BE_GlobalData::STREAM_IDL);
00085 
00086   std::string dc = be_global->header_name_.c_str();
00087   dc.replace(dc.end() - 6, dc.end() - 2, "C"); // s/Impl.h$/C.h/
00088   be_global->add_include(dc.c_str());
00089 
00090   static const char* h_includes[] = {
00091     "dds/DCPS/TypeSupportImpl.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", "dds/DCPS/DataWriterImpl_T.h",
00104     "dds/DCPS/DataReaderImpl_T.h"
00105   };
00106   add_includes(cpp_includes, BE_GlobalData::STREAM_CPP);
00107 
00108   std::map<std::string, std::string> replacements;
00109   replacements["SCOPED"] = cxxName;
00110   replacements["TYPE"] = short_name;
00111   replacements["EXPORT"] = be_global->export_macro().c_str();
00112   replacements["SEQ"] = be_global->sequence_suffix().c_str();
00113 
00114   ScopedNamespaceGuard idlGuard(name, be_global->idl_, "module");
00115   std::string idl = idl_template_;
00116   replaceAll(idl, replacements);
00117   be_global->idl_ << idl;
00118 
00119   be_global->header_ << be_global->versioning_begin() << "\n";
00120   {
00121     ScopedNamespaceGuard hGuard(name, be_global->header_);
00122 
00123     be_global->header_ <<
00124       "class " << short_name << "TypeSupportImpl;\n";
00125   }
00126   be_global->header_ << be_global->versioning_end() << "\n";
00127 
00128   const bool has_keys = info->key_list_.is_empty();
00129 
00130   be_global->header_ <<
00131     "OPENDDS_BEGIN_VERSIONED_NAMESPACE_DECL\n"
00132     "namespace OpenDDS { namespace DCPS {\n"
00133     "template <>\n"
00134     "struct DDSTraits<" << cxxName << "> {\n"
00135     "  typedef " << cxxName << " MessageType;\n"
00136     "  typedef " << cxxName << "Seq MessageSequenceType;\n"
00137     "  typedef " << cxxName << "TypeSupport TypeSupportType;\n"
00138     "  typedef " << cxxName << "TypeSupportImpl TypeSupportTypeImpl;\n"
00139     "  typedef " << cxxName << "DataWriter DataWriterType;\n"
00140     "  typedef " << cxxName << "DataReader DataReaderType;\n"
00141     "  typedef " << cxxName << "_OpenDDS_KeyLessThan LessThanType;\n"
00142     "\n"
00143     "  static const char* type_name () { return \"" << cxxName << "\"; }\n"
00144     "  static bool gen_has_key () { return " << (has_keys ? "false" : "true") << "; }\n"
00145     "\n"
00146     "  static size_t gen_max_marshaled_size(const MessageType& x, bool align) { return ::OpenDDS::DCPS::gen_max_marshaled_size(x, align); }\n"
00147     "  static void gen_find_size(const MessageType& arr, size_t& size, size_t& padding) { ::OpenDDS::DCPS::gen_find_size(arr, size, padding); }\n"
00148     "\n"
00149     "  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"
00150     "  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"
00151     "};\n}  }\nOPENDDS_END_VERSIONED_NAMESPACE_DECL\n\n";
00152 
00153   be_global->header_ << be_global->versioning_begin() << "\n";
00154   {
00155     ScopedNamespaceGuard hGuard(name, be_global->header_);
00156 
00157     be_global->header_ <<
00158       "class " << be_global->export_macro() << " " << short_name << "TypeSupportImpl\n"
00159       "  : public virtual OpenDDS::DCPS::LocalObject<" << short_name << "TypeSupport>\n"
00160       "  , public virtual OpenDDS::DCPS::TypeSupportImpl\n"
00161       "{\n"
00162       "public:\n"
00163       "  typedef OpenDDS::DCPS::DDSTraits<" << short_name << "> TraitsType;\n"
00164       "  typedef " << short_name << "TypeSupport TypeSupportType;\n"
00165       "  typedef " << short_name << "TypeSupport::_var_type _var_type;\n"
00166       "  typedef " << short_name << "TypeSupport::_ptr_type _ptr_type;\n"
00167       "\n"
00168       "  " << short_name << "TypeSupportImpl() {}\n"
00169       "  virtual ~" << short_name << "TypeSupportImpl() {}\n"
00170       "\n"
00171       "  virtual " << be_global->versioning_name() << "::DDS::DataWriter_ptr create_datawriter();\n"
00172       "  virtual " << be_global->versioning_name() << "::DDS::DataReader_ptr create_datareader();\n"
00173       "#ifndef OPENDDS_NO_MULTI_TOPIC\n"
00174       "  virtual " << be_global->versioning_name() << "::DDS::DataReader_ptr create_multitopic_datareader();\n"
00175       "#endif /* !OPENDDS_NO_MULTI_TOPIC */\n"
00176       "#ifndef OPENDDS_NO_CONTENT_SUBSCRIPTION_PROFILE\n"
00177       "  virtual const OpenDDS::DCPS::MetaStruct& getMetaStructForType();\n"
00178       "#endif /* !OPENDDS_NO_CONTENT_SUBSCRIPTION_PROFILE */\n"
00179       "  virtual bool has_dcps_key();\n"
00180       "  const char* default_type_name() const;\n"
00181       "  static " << short_name << "TypeSupport::_ptr_type _narrow(CORBA::Object_ptr obj);\n"
00182       "};\n";
00183   }
00184   be_global->header_ << be_global->versioning_end() << "\n";
00185 
00186   be_global->impl_ << be_global->versioning_begin() << "\n";
00187   {
00188     ScopedNamespaceGuard cppGuard(name, be_global->impl_);
00189     be_global->impl_ <<
00190       "::DDS::DataWriter_ptr " << short_name << "TypeSupportImpl::create_datawriter()\n"
00191       "{\n"
00192       "  typedef OpenDDS::DCPS::DataWriterImpl_T<" << short_name << "> DataWriterImplType;\n"
00193       "  ::DDS::DataWriter_ptr writer_impl = ::DDS::DataWriter::_nil();\n"
00194       "  ACE_NEW_NORETURN(writer_impl,\n"
00195       "                   DataWriterImplType());\n"
00196       "  return writer_impl;\n"
00197       "}\n\n"
00198       "::DDS::DataReader_ptr " << short_name << "TypeSupportImpl::create_datareader()\n"
00199       "{\n"
00200       "  typedef OpenDDS::DCPS::DataReaderImpl_T<" << short_name << "> DataReaderImplType;\n"
00201       "  ::DDS::DataReader_ptr reader_impl = ::DDS::DataReader::_nil();\n"
00202       "  ACE_NEW_NORETURN(reader_impl,\n"
00203       "                   DataReaderImplType());\n"
00204       "  return reader_impl;\n"
00205       "}\n\n"
00206       "#ifndef OPENDDS_NO_MULTI_TOPIC\n"
00207       "::DDS::DataReader_ptr " << short_name << "TypeSupportImpl::create_multitopic_datareader()\n"
00208       "{\n"
00209       "  typedef OpenDDS::DCPS::DataReaderImpl_T<" << short_name << "> DataReaderImplType;\n"
00210       "  typedef OpenDDS::DCPS::MultiTopicDataReader_T<" << short_name << ", DataReaderImplType> MultiTopicDataReaderImplType;\n"
00211       "  ::DDS::DataReader_ptr multitopic_reader_impl = ::DDS::DataReader::_nil();\n"
00212       "  ACE_NEW_NORETURN(multitopic_reader_impl,\n"
00213       "                   MultiTopicDataReaderImplType());\n"
00214       "  return multitopic_reader_impl;\n"
00215       "}\n"
00216       "#endif /* !OPENDDS_NO_MULTI_TOPIC */\n\n"
00217       "#ifndef OPENDDS_NO_CONTENT_SUBSCRIPTION_PROFILE\n"
00218       "const OpenDDS::DCPS::MetaStruct& " << short_name << "TypeSupportImpl::getMetaStructForType()\n"
00219       "{\n"
00220       "  return OpenDDS::DCPS::getMetaStruct<" << short_name << ">();\n"
00221       "}\n"
00222       "#endif /* !OPENDDS_NO_CONTENT_SUBSCRIPTION_PROFILE */\n\n"
00223       "bool " << short_name << "TypeSupportImpl::has_dcps_key()\n"
00224       "{\n"
00225       "  return TraitsType::gen_has_key ();\n"
00226       "}\n\n"
00227       "const char* " << short_name << "TypeSupportImpl::default_type_name() const\n"
00228       "{\n"
00229       "  return TraitsType::type_name();\n"
00230       "}\n\n"
00231       << short_name << "TypeSupport::_ptr_type " << short_name << "TypeSupportImpl::_narrow(CORBA::Object_ptr obj)\n"
00232       "{\n"
00233       "  return TypeSupportType::_narrow(obj);\n"
00234       "}\n";
00235   }
00236   be_global->impl_ << be_global->versioning_end() << "\n";
00237 
00238   if (be_global->face_ts()) {
00239     face_ts_generator::generate(name);
00240   }
00241 
00242   return true;
00243 }
00244 
00245 bool ts_generator::gen_union(AST_Union*, UTL_ScopedName* name,
00246   const std::vector<AST_UnionBranch*>&, AST_Type*, const char*)
00247 {
00248   if (idl_global->is_dcps_type(name)) {
00249     std::cerr << "ERROR: union " << scoped(name) << " can not be used as a "
00250       "DCPS_DATA_TYPE (only structs can be Topic types)" << std::endl;
00251     return false;
00252   }
00253   return true;
00254 }
00255 
00256 namespace java_ts_generator {
00257 
00258   /// called directly by dds_visitor::visit_structure() if -Wb,java
00259   void generate(UTL_ScopedName* name) {
00260     if (idl_global->is_dcps_type(name) == 0) {
00261       // no #pragma DCPS_DATA_TYPE, so nothing to generate
00262       return;
00263     }
00264 
00265     ACE_CString output_file = be_global->java_arg();
00266     if (output_file.length()) {
00267       be_global->impl_name_ = output_file;
00268     }
00269     be_global->add_include("idl2jni_jni.h", BE_GlobalData::STREAM_CPP);
00270 
00271     std::string type = scoped(name);
00272 
00273     std::string file, jniclass, jpackage;
00274     for (UTL_ScopedName* sn = name; sn;
00275         sn = static_cast<UTL_ScopedName*>(sn->tail())) {
00276       std::string tmp = sn->head()->get_string();
00277       if (tmp != "" && sn->tail()) {
00278         jpackage += tmp;
00279         file += tmp;
00280         if (ACE_OS::mkdir(file.c_str()) != 0 && errno != EEXIST) {
00281           ACE_ERROR((LM_ERROR, ACE_TEXT("ERROR: java_ts_generator::generate - ")
00282             ACE_TEXT("unable to create specified directory: %C"), file.c_str()));
00283         }
00284       }
00285       for (size_t i = tmp.find('_'); i < tmp.length();
00286           i = tmp.find('_', i + 1)) {
00287         tmp.insert(++i, 1, '1');
00288       }
00289       jniclass += tmp;
00290       if (jniclass != "" && sn->tail()) {
00291         jniclass += '_';
00292         jpackage += '.';
00293         file += '/';
00294       }
00295     }
00296 
00297     if (jpackage.size() && jpackage[jpackage.size() - 1] == '.') {
00298       jpackage.resize(jpackage.size() - 1);
00299     }
00300 
00301     std::string clazz = name->last_component()->get_string();
00302     file += clazz + "TypeSupportImpl.java";
00303 
00304     std::ofstream java(file.c_str());
00305     java << (jpackage.size() ? "package " : "") << jpackage
00306       << (jpackage.size() ? ";\n" :"") <<
00307       "public class " << clazz << "TypeSupportImpl extends _" << clazz
00308       << "TypeSupportTAOPeer {\n"
00309       "    public " << clazz << "TypeSupportImpl() {\n"
00310       "        super(_jni_init());\n"
00311       "    }\n"
00312       "    private static native long _jni_init();\n"
00313       "}\n";
00314     be_global->impl_ <<
00315       "extern \"C\" JNIEXPORT jlong JNICALL\n"
00316       "Java_" << jniclass << "TypeSupportImpl__1jni_1init(JNIEnv*, jclass) {\n"
00317       "  return reinterpret_cast<jlong>(static_cast<CORBA::Object_ptr>(new "
00318       << type << "TypeSupportImpl));\n"
00319       "}\n\n";
00320   }
00321 
00322 }
00323 
00324 namespace face_ts_generator {
00325 
00326   void generate(UTL_ScopedName* name) {
00327     const std::string name_cxx = scoped(name),
00328       name_underscores = dds_generator::scoped_helper(name, "_"),
00329       exportMacro = be_global->export_macro().c_str(),
00330       exporter = exportMacro.empty() ? "" : ("    " + exportMacro + '\n');
00331     be_global->add_include("FACE/TS.hpp", BE_GlobalData::STREAM_FACETS_H);
00332     be_global->facets_header_ <<
00333       "namespace FACE\n"
00334       "{\n"
00335       "  namespace Read_Callback\n"
00336       "  {\n"
00337       "    typedef void (*send_event_" << name_underscores << "_Ptr) (\n"
00338       "      /* in */ TRANSACTION_ID_TYPE transaction_id,\n"
00339       "      /* inout */ " << name_cxx << "& message,\n"
00340       "      /* in */ MESSAGE_TYPE_GUID message_type_id,\n"
00341       "      /* in */ MESSAGE_SIZE_TYPE message_size,\n"
00342       "      /* in */ const WAITSET_TYPE waitset,\n"
00343       "      /* out */ RETURN_CODE_TYPE& return_code);\n"
00344       "  }\n\n"
00345       "  namespace TS\n"
00346       "  {\n" << exporter <<
00347       "    void Receive_Message(\n"
00348       "      /* in */ CONNECTION_ID_TYPE connection_id,\n"
00349       "      /* in */ TIMEOUT_TYPE timeout,\n"
00350       "      /* inout */ TRANSACTION_ID_TYPE& transaction_id,\n"
00351       "      /* out */ " << name_cxx << "& message,\n"
00352       "      /* in */ MESSAGE_SIZE_TYPE message_size,\n"
00353       "      /* out */ RETURN_CODE_TYPE& return_code);\n\n" << exporter <<
00354       "    void Send_Message(\n"
00355       "      /* in */ CONNECTION_ID_TYPE connection_id,\n"
00356       "      /* in */ TIMEOUT_TYPE timeout,\n"
00357       "      /* inout */ TRANSACTION_ID_TYPE& transaction_id,\n"
00358       "      /* inout */ " << name_cxx << "& message,\n"
00359       "      /* inout */ MESSAGE_SIZE_TYPE& message_size,\n"
00360       "      /* out */ RETURN_CODE_TYPE& return_code);\n\n" << exporter <<
00361       "    void Register_Callback(\n"
00362       "      /* in */ CONNECTION_ID_TYPE connection_id,\n"
00363       "      /* in */ const WAITSET_TYPE waitset,\n"
00364       "      /* in */ Read_Callback::send_event_" << name_underscores
00365                     << "_Ptr data_callback,\n"
00366       "      /* in */ MESSAGE_SIZE_TYPE max_message_size,\n"
00367       "      /* out */ RETURN_CODE_TYPE& return_code);\n\n"
00368       "  }\n"
00369       "}\n\n";
00370     be_global->facets_impl_ <<
00371       "void Receive_Message(CONNECTION_ID_TYPE connection_id,\n"
00372       "                     TIMEOUT_TYPE timeout,\n"
00373       "                     TRANSACTION_ID_TYPE& transaction_id,\n"
00374       "                     " << name_cxx << "& message,\n"
00375       "                     MESSAGE_SIZE_TYPE message_size,\n"
00376       "                     RETURN_CODE_TYPE& return_code) {\n"
00377       "  OpenDDS::FaceTSS::receive_message(connection_id, timeout,\n"
00378       "                                    transaction_id, message,\n"
00379       "                                    message_size, return_code);\n"
00380       "}\n\n"
00381       "void Send_Message(CONNECTION_ID_TYPE connection_id,\n"
00382       "                  TIMEOUT_TYPE timeout,\n"
00383       "                  TRANSACTION_ID_TYPE& transaction_id,\n"
00384       "                  " << name_cxx << "& message,\n"
00385       "                  MESSAGE_SIZE_TYPE& message_size,\n"
00386       "                  RETURN_CODE_TYPE& return_code) {\n"
00387       "  OpenDDS::FaceTSS::send_message(connection_id, timeout,\n"
00388       "                                 transaction_id, message,\n"
00389       "                                 message_size, return_code);\n"
00390       "}\n\n"
00391       "void Register_Callback(CONNECTION_ID_TYPE connection_id,\n"
00392       "                       const WAITSET_TYPE waitset,\n"
00393       "                       Read_Callback::send_event_" << name_underscores
00394                           << "_Ptr data_callback,\n"
00395       "                       MESSAGE_SIZE_TYPE max_message_size,\n"
00396       "                       RETURN_CODE_TYPE& return_code) {\n"
00397       "  OpenDDS::FaceTSS::register_callback(connection_id, waitset,\n"
00398       "                                      data_callback,\n"
00399       "                                      max_message_size, return_code);\n"
00400       "}\n\n"
00401       "struct " << name_underscores << "_Initializer {\n"
00402       "  " << name_underscores << "_Initializer()\n"
00403       "  {\n"
00404       "    " << name_cxx << "TypeSupport_var ts = new " << name_cxx
00405                           << "TypeSupportImpl;\n"
00406       "    ts->register_type(0, \"\");\n"
00407       "  }\n"
00408       "} init_" << name_underscores << ";\n\n";
00409   }
00410 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated on 10 Aug 2018 for OpenDDS by  doxygen 1.6.1