metaclass_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 "metaclass_generator.h"
00009 #include "be_extern.h"
00010 
00011 #include "utl_identifier.h"
00012 
00013 using namespace AstTypeClassification;
00014 
00015 namespace {
00016   struct ContentSubscriptionGuard {
00017     explicit ContentSubscriptionGuard(bool activate = true)
00018       : activate_(activate)
00019     {
00020       if (activate) {
00021         be_global->header_ <<
00022           "#ifndef OPENDDS_NO_CONTENT_SUBSCRIPTION_PROFILE\n";
00023         be_global->impl_ <<
00024           "#ifndef OPENDDS_NO_CONTENT_SUBSCRIPTION_PROFILE\n";
00025       }
00026     }
00027     ~ContentSubscriptionGuard()
00028     {
00029       if (activate_) {
00030         be_global->header_ << "#endif\n";
00031         be_global->impl_ << "#endif\n";
00032       }
00033     }
00034     bool activate_;
00035   };
00036 }
00037 
00038 bool metaclass_generator::gen_enum(AST_Enum*, UTL_ScopedName* name,
00039   const std::vector<AST_EnumVal*>& contents, const char*)
00040 {
00041   ContentSubscriptionGuard csg(!be_global->v8());
00042   NamespaceGuard ng;
00043   std::string decl = "const char* gen_" + scoped_helper(name, "_") + "_names[]";
00044   be_global->header_ << "extern " << decl << ";\n";
00045   be_global->impl_ << decl << " = {\n";
00046   for (size_t i = 0; i < contents.size(); ++i) {
00047     be_global->impl_ << "  \"" << contents[i]->local_name()->get_string()
00048       << ((i < contents.size() - 1) ? "\",\n" : "\"\n");
00049   }
00050   be_global->impl_ << "};\n";
00051   return true;
00052 }
00053 
00054 namespace {
00055 
00056   void delegateToNested(const std::string& fieldName, AST_Field* field,
00057                         const std::string& firstArg, bool skip = false)
00058   {
00059     const size_t n = fieldName.size() + 1 /* 1 for the dot */;
00060     const std::string fieldType = scoped(field->field_type()->name());
00061     be_global->impl_ <<
00062       "    if (std::strncmp(field, \"" << fieldName << ".\", " << n
00063       << ") == 0) {\n"
00064       "      return getMetaStruct<" << fieldType << ">().getValue("
00065       << firstArg << ", field + " << n << ");\n"
00066       "    }" << (skip ? "" : "\n");
00067     if (skip) {
00068       be_global->impl_ << " else {\n"
00069         "      gen_skip_over(" << firstArg << ", static_cast<" << fieldType
00070         << "*>(0));\n"
00071         "    }\n";
00072     }
00073   }
00074 
00075   void gen_field_getValue(AST_Field* field)
00076   {
00077     const Classification cls = classify(field->field_type());
00078     const std::string fieldName = field->local_name()->get_string();
00079     if (cls & CL_SCALAR) {
00080       std::string prefix, suffix;
00081       if (cls & CL_ENUM) {
00082         AST_Type* enum_type = resolveActualType(field->field_type());
00083         prefix = "gen_" +
00084           dds_generator::scoped_helper(enum_type->name(), "_")
00085           + "_names[";
00086         suffix = "]";
00087       }
00088       be_global->impl_ <<
00089         "    if (std::strcmp(field, \"" << fieldName << "\") == 0) {\n"
00090         "      return " + prefix + "typed." + fieldName
00091         + (cls & CL_STRING ? ".in()" : "") + suffix + ";\n"
00092         "    }\n";
00093       be_global->add_include("<cstring>", BE_GlobalData::STREAM_CPP);
00094     } else if (cls & CL_STRUCTURE) {
00095       delegateToNested(fieldName, field, "&typed." + fieldName);
00096       be_global->add_include("<cstring>", BE_GlobalData::STREAM_CPP);
00097     }
00098   }
00099 
00100   std::string to_cxx_type(AST_Type* type, int& size)
00101   {
00102     const Classification cls = classify(type);
00103     if (cls & CL_ENUM) {
00104       size = 4;
00105       return "ACE_CDR::ULong";
00106     }
00107     if (cls & CL_STRING) {
00108       size = 4; // encoding of str length is 4 bytes
00109       return ((cls & CL_WIDE) ? "TAO::W" : "TAO::")
00110         + std::string("String_Manager");
00111     }
00112     if (cls & CL_PRIMITIVE) {
00113       type = resolveActualType(type);
00114       AST_PredefinedType* p = AST_PredefinedType::narrow_from_decl(type);
00115       switch (p->pt()) {
00116       case AST_PredefinedType::PT_long:
00117         size = 4;
00118         return "ACE_CDR::Long";
00119       case AST_PredefinedType::PT_ulong:
00120         size = 4;
00121         return "ACE_CDR::ULong";
00122       case AST_PredefinedType::PT_longlong:
00123         size = 8;
00124         return "ACE_CDR::LongLong";
00125       case AST_PredefinedType::PT_ulonglong:
00126         size = 8;
00127         return "ACE_CDR::ULongLong";
00128       case AST_PredefinedType::PT_short:
00129         size = 2;
00130         return "ACE_CDR::Short";
00131       case AST_PredefinedType::PT_ushort:
00132         size = 2;
00133         return "ACE_CDR::UShort";
00134       case AST_PredefinedType::PT_float:
00135         size = 4;
00136         return "ACE_CDR::Float";
00137       case AST_PredefinedType::PT_double:
00138         size = 8;
00139         return "ACE_CDR::Double";
00140       case AST_PredefinedType::PT_longdouble:
00141         size = 16;
00142         return "ACE_CDR::LongDouble";
00143       case AST_PredefinedType::PT_char:
00144         size = 1;
00145         return "ACE_CDR::Char";
00146       case AST_PredefinedType::PT_wchar:
00147         size = 1; // encoding of wchar length is 1 byte
00148         return "ACE_CDR::WChar";
00149       case AST_PredefinedType::PT_boolean:
00150         size = 1;
00151         return "ACE_CDR::Boolean";
00152       case AST_PredefinedType::PT_octet:
00153         size = 1;
00154         return "ACE_CDR::Octet";
00155       default:
00156         break;
00157       }
00158     }
00159     return scoped(type->name());
00160   }
00161 
00162   void gen_field_getValueFromSerialized(AST_Field* field)
00163   {
00164     AST_Type* type = field->field_type();
00165     const Classification cls = classify(type);
00166     const std::string fieldName = field->local_name()->get_string();
00167     int size = 0;
00168     const std::string cxx_type = to_cxx_type(type, size);
00169     if (cls & CL_SCALAR) {
00170       type = resolveActualType(type);
00171       const std::string val =
00172         (cls & CL_STRING) ? "val.out()" : getWrapper("val", type, WD_INPUT);
00173       be_global->impl_ <<
00174         "    if (std::strcmp(field, \"" << fieldName << "\") == 0) {\n"
00175         "      " << cxx_type << " val;\n"
00176         "      if (!(ser >> " << val << ")) {\n"
00177         "        throw std::runtime_error(\"Field '" << fieldName << "' could "
00178         "not be deserialized\");\n"
00179         "      }\n"
00180         "      return val;\n"
00181         "    } else {\n";
00182       if (cls & CL_STRING) {
00183         be_global->impl_ <<
00184           "      ACE_CDR::ULong len;\n"
00185           "      if (!(ser >> len)) {\n"
00186           "        throw std::runtime_error(\"String '" << fieldName <<
00187           "' length could not be deserialized\");\n"
00188           "      }\n"
00189           "      ser.skip(len);\n";
00190       } else if (cls & CL_WIDE) {
00191         be_global->impl_ <<
00192           "      ACE_CDR::Octet len;\n"
00193           "      if (!(ser >> ACE_InputCDR::to_octet(len))) {\n"
00194           "        throw std::runtime_error(\"WChar '" << fieldName <<
00195           "' length could not be deserialized\");\n"
00196           "      }\n"
00197           "      ser.skip(len);\n";
00198       } else {
00199         be_global->impl_ <<
00200           "      ser.skip(1, " << size << ");\n";
00201       }
00202       be_global->impl_ <<
00203         "    }\n";
00204     } else if (cls & CL_STRUCTURE) {
00205       delegateToNested(fieldName, field, "ser", true);
00206     } else { // array, sequence, union:
00207       be_global->impl_ <<
00208         "    gen_skip_over(ser, static_cast<" << cxx_type
00209         << ((cls & CL_ARRAY) ? "_forany" : "") << "*>(0));\n";
00210     }
00211   }
00212 
00213   void gen_field_createQC(AST_Field* field)
00214   {
00215     Classification cls = classify(field->field_type());
00216     const std::string fieldName = field->local_name()->get_string();
00217     if (cls & CL_SCALAR) {
00218       be_global->impl_ <<
00219         "    if (std::strcmp(field, \"" << fieldName << "\") == 0) {\n"
00220         "      return make_field_cmp(&T::" << fieldName << ", next);\n"
00221         "    }\n";
00222       be_global->add_include("<cstring>", BE_GlobalData::STREAM_CPP);
00223     } else if (cls & CL_STRUCTURE) {
00224       size_t n = fieldName.size() + 1 /* 1 for the dot */;
00225       std::string fieldType = scoped(field->field_type()->name());
00226       be_global->impl_ <<
00227         "    if (std::strncmp(field, \"" << fieldName << ".\", " << n <<
00228         ") == 0) {\n"
00229         "      return make_struct_cmp(&T::" << fieldName <<
00230         ", getMetaStruct<" << fieldType << ">().create_qc_comparator("
00231         "field + " << n << ", 0), next);\n"
00232         "    }\n";
00233     }
00234   }
00235 
00236   void print_field_name(AST_Field* field)
00237   {
00238     be_global->impl_ << '"' << field->local_name()->get_string() << '"' << ", ";
00239   }
00240 
00241   void get_raw_field(AST_Field* field)
00242   {
00243     const char* fieldName = field->local_name()->get_string();
00244     be_global->impl_ <<
00245       "    if (std::strcmp(field, \"" << fieldName << "\") == 0) {\n"
00246       "      return &static_cast<const T*>(stru)->" << fieldName << ";\n"
00247       "    }\n";
00248     be_global->add_include("<cstring>", BE_GlobalData::STREAM_CPP);
00249   }
00250 
00251   void assign_field(AST_Field* field)
00252   {
00253     Classification cls = classify(field->field_type());
00254     if (!cls) return; // skip CL_UNKNOWN types
00255     const char* fieldName = field->local_name()->get_string();
00256     const std::string fieldType = (cls & CL_STRING) ?
00257       ((cls & CL_WIDE) ? "TAO::WString_Manager" : "TAO::String_Manager")
00258       : scoped(field->field_type()->name());
00259     if (cls & (CL_SCALAR | CL_STRUCTURE | CL_SEQUENCE | CL_UNION)) {
00260       be_global->impl_ <<
00261         "    if (std::strcmp(field, \"" << fieldName << "\") == 0) {\n"
00262         "      static_cast<T*>(lhs)->" << fieldName <<
00263         " = *static_cast<const " << fieldType <<
00264         "*>(rhsMeta.getRawField(rhs, rhsFieldSpec));\n"
00265         "      return;\n"
00266         "    }\n";
00267       be_global->add_include("<cstring>", BE_GlobalData::STREAM_CPP);
00268     } else if (cls & CL_ARRAY) {
00269       AST_Type* unTD = resolveActualType(field->field_type());
00270       AST_Array* arr = AST_Array::narrow_from_decl(unTD);
00271       be_global->impl_ <<
00272         "    if (std::strcmp(field, \"" << fieldName << "\") == 0) {\n"
00273         "      " << fieldType << "* lhsArr = &static_cast<T*>(lhs)->" <<
00274         fieldName << ";\n"
00275         "      const " << fieldType << "* rhsArr = static_cast<const " <<
00276         fieldType << "*>(rhsMeta.getRawField(rhs, rhsFieldSpec));\n";
00277       be_global->add_include("<cstring>", BE_GlobalData::STREAM_CPP);
00278       AST_Type* elem = arr->base_type();
00279       AST_Type* elemUnTD = resolveActualType(elem);
00280       if (classify(elemUnTD) & CL_ARRAY) {
00281         // array-of-array case, fall back on the Serializer
00282         be_global->impl_ <<
00283           "      " << fieldType << "_forany rhsForany(const_cast<" <<
00284           fieldType << "_slice*>(*rhsArr));\n"
00285           "      size_t size = 0, padding = 0;\n"
00286           "      gen_find_size(rhsForany, size, padding);\n"
00287           "      ACE_Message_Block mb(size);\n"
00288           "      Serializer ser_out(&mb);\n"
00289           "      ser_out << rhsForany;\n"
00290           "      " << fieldType << "_forany lhsForany(*lhsArr);\n"
00291           "      Serializer ser_in(&mb);\n"
00292           "      ser_in >> lhsForany;\n";
00293       } else {
00294         std::string indent = "      ";
00295         NestedForLoops nfl("CORBA::ULong", "i", arr, indent);
00296         be_global->impl_ <<
00297           indent << "(*lhsArr)" << nfl.index_ << " = (*rhsArr)" <<
00298           nfl.index_ << ";\n";
00299       }
00300       be_global->impl_ <<
00301         "      return;\n"
00302         "    }\n";
00303     }
00304   }
00305 
00306   void compare_field(AST_Field* field)
00307   {
00308     Classification cls = classify(field->field_type());
00309     if (!(cls & CL_SCALAR)) return;
00310     const char* fieldName = field->local_name()->get_string();
00311     be_global->impl_ <<
00312       "    if (std::strcmp(field, \"" << fieldName << "\") == 0) {\n";
00313     be_global->add_include("<cstring>", BE_GlobalData::STREAM_CPP);
00314     if (cls & CL_STRING) {
00315       be_global->impl_ << // ACE_OS::strcmp has overloads for narrow & wide
00316         "      return 0 == ACE_OS::strcmp(static_cast<const T*>(lhs)->"
00317         << fieldName << ".in(), static_cast<const T*>(rhs)->" << fieldName
00318         << ".in());\n";
00319     } else {
00320       be_global->impl_ <<
00321         "      return static_cast<const T*>(lhs)->" << fieldName <<
00322         " == static_cast<const T*>(rhs)->" << fieldName << ";\n";
00323     }
00324     be_global->impl_ << "    }\n";
00325   }
00326 }
00327 
00328 bool metaclass_generator::gen_struct(AST_Structure*, UTL_ScopedName* name,
00329   const std::vector<AST_Field*>& fields, AST_Type::SIZE_TYPE, const char*)
00330 {
00331   ContentSubscriptionGuard csg;
00332   NamespaceGuard ng;
00333   be_global->add_include("dds/DCPS/PoolAllocator.h",
00334     BE_GlobalData::STREAM_CPP);
00335   be_global->add_include("dds/DCPS/FilterEvaluator.h",
00336     BE_GlobalData::STREAM_CPP);
00337   if (first_struct_) {
00338     be_global->header_ <<
00339       "class MetaStruct;\n\n"
00340       "template<typename T>\n"
00341       "const MetaStruct& getMetaStruct();\n\n";
00342     first_struct_ = false;
00343   }
00344 
00345   size_t nKeys = 0;
00346   IDL_GlobalData::DCPS_Data_Type_Info* info = idl_global->is_dcps_type(name);
00347   if (info) {
00348     nKeys = info->key_list_.size();
00349   }
00350 
00351   std::string clazz = scoped(name);
00352   std::string decl = "const MetaStruct& getMetaStruct<" + clazz + ">()",
00353     exp = be_global->export_macro().c_str();
00354   be_global->header_ << "template<>\n" << exp << (exp.length() ? "\n" : "")
00355     << decl << ";\n";
00356 
00357   be_global->impl_ <<
00358     "template<>\n"
00359     "struct MetaStructImpl<" << clazz << "> : MetaStruct {\n"
00360     "  typedef " << clazz << " T;\n\n"
00361     "  void* allocate() const { return new T; }\n\n"
00362     "  void deallocate(void* stru) const { delete static_cast<T*>(stru); }\n\n"
00363     "  size_t numDcpsKeys() const { return " << nKeys << "; }\n\n"
00364     "  Value getValue(const void* stru, const char* field) const\n"
00365     "  {\n"
00366     "    const " << clazz << "& typed = *static_cast<const " << clazz
00367     << "*>(stru);\n";
00368   std::for_each(fields.begin(), fields.end(), gen_field_getValue);
00369   const std::string exception =
00370     "    throw std::runtime_error(\"Field \" + OPENDDS_STRING(field) + \" not "
00371     "found or its type is not supported (in struct " + clazz + ")\");\n";
00372   be_global->impl_ <<
00373     "    ACE_UNUSED_ARG(typed);\n" <<
00374     exception <<
00375     "  }\n\n"
00376     "  Value getValue(Serializer& ser, const char* field) const\n"
00377     "  {\n";
00378   std::for_each(fields.begin(), fields.end(), gen_field_getValueFromSerialized);
00379   be_global->impl_ <<
00380     "    if (!field[0]) {\n"   // if 'field' is the empty string...
00381     "      return 0;\n"        // ...we've skipped the entire struct
00382     "    }\n"                  //    and the return value is ignored
00383     "    throw std::runtime_error(\"Field \" + OPENDDS_STRING(field) + \" not "
00384     "valid for struct " << clazz << "\");\n"
00385     "  }\n\n"
00386     "  ComparatorBase::Ptr create_qc_comparator(const char* field, "
00387     "ComparatorBase::Ptr next) const\n"
00388     "  {\n"
00389     "    ACE_UNUSED_ARG(next);\n";
00390   be_global->add_include("<stdexcept>", BE_GlobalData::STREAM_CPP);
00391   std::for_each(fields.begin(), fields.end(), gen_field_createQC);
00392   be_global->impl_ <<
00393     exception <<
00394     "  }\n\n"
00395     "  const char** getFieldNames() const\n"
00396     "  {\n"
00397     "    static const char* names[] = {";
00398   std::for_each(fields.begin(), fields.end(), print_field_name);
00399   be_global->impl_ <<
00400     "0};\n"
00401     "    return names;\n"
00402     "  }\n\n"
00403     "  const void* getRawField(const void* stru, const char* field) const\n"
00404     "  {\n";
00405   std::for_each(fields.begin(), fields.end(), get_raw_field);
00406   be_global->impl_ <<
00407     exception <<
00408     "  }\n\n"
00409     "  void assign(void* lhs, const char* field, const void* rhs,\n"
00410     "    const char* rhsFieldSpec, const MetaStruct& rhsMeta) const\n"
00411     "  {\n"
00412     "    ACE_UNUSED_ARG(lhs);\n"
00413     "    ACE_UNUSED_ARG(field);\n"
00414     "    ACE_UNUSED_ARG(rhs);\n"
00415     "    ACE_UNUSED_ARG(rhsFieldSpec);\n"
00416     "    ACE_UNUSED_ARG(rhsMeta);\n";
00417   std::for_each(fields.begin(), fields.end(), assign_field);
00418   be_global->impl_ <<
00419     exception <<
00420     "  }\n\n"
00421     "  bool compare(const void* lhs, const void* rhs, const char* field) "
00422     "const\n"
00423     "  {\n"
00424     "    ACE_UNUSED_ARG(lhs);\n"
00425     "    ACE_UNUSED_ARG(field);\n"
00426     "    ACE_UNUSED_ARG(rhs);\n";
00427   std::for_each(fields.begin(), fields.end(), compare_field);
00428   be_global->impl_ <<
00429     exception <<
00430     "  }\n"
00431     "};\n\n"
00432     "template<>\n"
00433     << decl << "\n"
00434     "{\n"
00435     "  static MetaStructImpl<" << clazz << "> msi;\n"
00436     "  return msi;\n"
00437     "}\n\n";
00438   {
00439     Function f("gen_skip_over", "void");
00440     f.addArg("ser", "Serializer&");
00441     f.addArg("", clazz + "*");
00442     f.endArgs();
00443     be_global->impl_ <<
00444       "  MetaStructImpl<" << clazz << ">().getValue(ser, \"\");\n";
00445   }
00446   return true;
00447 }
00448 
00449 bool
00450 metaclass_generator::gen_typedef(AST_Typedef*, UTL_ScopedName* name, AST_Type* type, const char*)
00451 {
00452   AST_Array* arr = AST_Array::narrow_from_decl(type);
00453   AST_Sequence* seq = 0;
00454   if (!arr && !(seq = AST_Sequence::narrow_from_decl(type))) {
00455     return true;
00456   }
00457 
00458   const Classification cls = classify(type);
00459   const std::string clazz = scoped(name);
00460   ContentSubscriptionGuard csg;
00461   NamespaceGuard ng;
00462   Function f("gen_skip_over", "void");
00463   f.addArg("ser", "Serializer&");
00464   f.addArg("", clazz + ((cls & CL_ARRAY) ? "_forany*" : "*"));
00465   f.endArgs();
00466 
00467   std::string len;
00468   AST_Type* elem;
00469 
00470   if (arr) {
00471     elem = arr->base_type();
00472     size_t n_elems = 1;
00473     for (size_t i = 0; i < arr->n_dims(); ++i) {
00474       n_elems *= arr->dims()[i]->ev()->u.ulval;
00475     }
00476     std::ostringstream strstream;
00477     strstream << n_elems;
00478     len = strstream.str();
00479   } else { // Sequence
00480     elem = seq->base_type();
00481     be_global->impl_ <<
00482       "  ACE_CDR::ULong length;\n"
00483       "  ser >> length;\n";
00484     len = "length";
00485   }
00486 
00487   const std::string cxx_elem = scoped(elem->name());
00488   elem = resolveActualType(elem);
00489   const Classification elem_cls = classify(elem);
00490 
00491   if ((elem_cls & (CL_PRIMITIVE | CL_ENUM)) && !(elem_cls & CL_WIDE)) {
00492     // fixed-length sequence/array element -> skip all elements at once
00493     int sz = 1;
00494     to_cxx_type(elem, sz);
00495     be_global->impl_ <<
00496       "  ser.skip(" << len << ", " << sz << ");\n";
00497   } else {
00498     be_global->impl_ <<
00499       "  for (ACE_CDR::ULong i = 0; i < " << len << "; ++i) {\n";
00500     if ((elem_cls & CL_PRIMITIVE) && (elem_cls & CL_WIDE)) {
00501       be_global->impl_ <<
00502         "    ACE_CDR::Octet o;\n"
00503         "    ser >> ACE_InputCDR::to_octet(o);\n"
00504         "    ser.skip(o);\n";
00505     } else if (elem_cls & CL_STRING) {
00506       be_global->impl_ <<
00507         "    ACE_CDR::ULong strlength;\n"
00508         "    ser >> strlength;\n"
00509         "    ser.skip(strlength);\n";
00510     } else if (elem_cls & (CL_ARRAY | CL_SEQUENCE | CL_STRUCTURE)) {
00511       be_global->impl_ <<
00512         "    gen_skip_over(ser, static_cast<" << cxx_elem
00513         << ((elem_cls & CL_ARRAY) ? "_forany" : "") << "*>(0));\n";
00514     }
00515     be_global->impl_ <<
00516       "  }\n";
00517   }
00518 
00519   return true;
00520 }
00521 
00522 static std::string func(const std::string&,
00523                         AST_Type* br_type,
00524                         const std::string&,
00525                         std::string&,
00526                         const std::string&)
00527 {
00528   std::stringstream ss;
00529   const Classification br_cls = classify(br_type);
00530   if (br_cls & CL_STRING) {
00531     ss <<
00532       "      ACE_CDR::ULong len;\n"
00533       "      ser >> len;\n"
00534       "      ser.skip(len);\n";
00535   } else if (br_cls & CL_WIDE) {
00536     ss <<
00537       "      ACE_CDR::Octet len;\n"
00538       "      ser >> ACE_InputCDR::to_octet(len);\n"
00539       "      ser.skip(len);\n";
00540   } else if (br_cls & CL_SCALAR) {
00541     int sz = 1;
00542     to_cxx_type(br_type, sz);
00543     ss <<
00544       "    ser.skip(1, " << sz << ");\n";
00545   } else {
00546     ss <<
00547       "    gen_skip_over(ser, static_cast<" << scoped(br_type->name())
00548                                             << ((br_cls & CL_ARRAY) ? "_forany" : "") << "*>(0));\n";
00549   }
00550 
00551   return ss.str();
00552 }
00553 
00554 bool
00555 metaclass_generator::gen_union(AST_Union*, UTL_ScopedName* name,
00556   const std::vector<AST_UnionBranch*>& branches, AST_Type* discriminator,
00557   const char*)
00558 {
00559   const std::string clazz = scoped(name);
00560   ContentSubscriptionGuard csg;
00561   NamespaceGuard ng;
00562   Function f("gen_skip_over", "void");
00563   f.addArg("ser", "Serializer&");
00564   f.addArg("", clazz + "*");
00565   f.endArgs();
00566   be_global->impl_ <<
00567     "  " << scoped(discriminator->name()) << " disc;\n"
00568     "  if (!(ser >> " << getWrapper("disc", discriminator, WD_INPUT) << ")) {\n"
00569     "    return;\n"
00570     "  }\n";
00571   generateSwitchForUnion("disc", func, branches, discriminator, "");
00572   return true;
00573 }

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