00001
00002
00003
00004
00005
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 ;
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;
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;
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 {
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 ;
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;
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
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_ <<
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"
00381 " return 0;\n"
00382 " }\n"
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 {
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
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 }