00001
00002
00003
00004
00005
00006
00007
00008 #include "marshal_generator.h"
00009 #include "be_extern.h"
00010 #include "utl_identifier.h"
00011 #include <string>
00012 #include <sstream>
00013 #include <iostream>
00014 #include <cctype>
00015 #include <map>
00016
00017 using std::string;
00018 using namespace AstTypeClassification;
00019
00020 #define LENGTH(CARRAY) (sizeof(CARRAY)/sizeof(CARRAY[0]))
00021
00022 namespace {
00023
00024 typedef bool (*is_special_case)(const string& cxx);
00025 typedef bool (*gen_special_case)(const string& cxx);
00026
00027 typedef is_special_case is_special_sequence;
00028 typedef gen_special_case gen_special_sequence;
00029
00030 typedef is_special_case is_special_struct;
00031 typedef gen_special_case gen_special_struct;
00032
00033 typedef is_special_case is_special_union;
00034 typedef bool (*gen_special_union)(const string& cxx,
00035 AST_Type* discriminator,
00036 const std::vector<AST_UnionBranch*>& branches);
00037
00038 struct special_sequence
00039 {
00040 is_special_sequence check;
00041 gen_special_sequence gen;
00042 };
00043
00044 struct special_struct
00045 {
00046 is_special_struct check;
00047 gen_special_struct gen;
00048 };
00049
00050 struct special_union
00051 {
00052 is_special_union check;
00053 gen_special_union gen;
00054 };
00055
00056 bool isRtpsSpecialSequence(const string& cxx);
00057 bool genRtpsSpecialSequence(const string& cxx);
00058
00059 bool isPropertySpecialSequence(const string& cxx);
00060 bool genPropertySpecialSequence(const string& cxx);
00061
00062 bool isRtpsSpecialStruct(const string& cxx);
00063 bool genRtpsSpecialStruct(const string& cxx);
00064
00065 bool isRtpsSpecialUnion(const string& cxx);
00066 bool genRtpsSpecialUnion(const string& cxx,
00067 AST_Type* discriminator,
00068 const std::vector<AST_UnionBranch*>& branches);
00069
00070 bool isProperty_t(const string& cxx);
00071 bool genProperty_t(const string& cxx);
00072
00073 bool isBinaryProperty_t(const string& cxx);
00074 bool genBinaryProperty_t(const string& cxx);
00075
00076 bool isPropertyQosPolicy(const string& cxx);
00077 bool genPropertyQosPolicy(const string& cxx);
00078
00079 bool isSecuritySubmessage(const string& cxx);
00080 bool genSecuritySubmessage(const string& cxx);
00081
00082 const special_sequence special_sequences[] = {
00083 {
00084 isRtpsSpecialSequence,
00085 genRtpsSpecialSequence,
00086 },
00087 {
00088 isPropertySpecialSequence,
00089 genPropertySpecialSequence,
00090 },
00091 };
00092
00093 const special_struct special_structs[] = {
00094 {
00095 isRtpsSpecialStruct,
00096 genRtpsSpecialStruct,
00097 },
00098 {
00099 isProperty_t,
00100 genProperty_t,
00101 },
00102 {
00103 isBinaryProperty_t,
00104 genBinaryProperty_t,
00105 },
00106 {
00107 isPropertyQosPolicy,
00108 genPropertyQosPolicy,
00109 },
00110 {
00111 isSecuritySubmessage,
00112 genSecuritySubmessage,
00113 },
00114 };
00115
00116 const special_union special_unions[] = {
00117 {
00118 isRtpsSpecialUnion,
00119 genRtpsSpecialUnion,
00120 },
00121 };
00122
00123 }
00124
00125 bool marshal_generator::gen_enum(AST_Enum*, UTL_ScopedName* name,
00126 const std::vector<AST_EnumVal*>&, const char*)
00127 {
00128 NamespaceGuard ng;
00129 be_global->add_include("dds/DCPS/Serializer.h");
00130 string cxx = scoped(name);
00131 {
00132 Function insertion("operator<<", "bool");
00133 insertion.addArg("strm", "Serializer&");
00134 insertion.addArg("enumval", "const " + cxx + "&");
00135 insertion.endArgs();
00136 be_global->impl_ <<
00137 " return strm << static_cast<CORBA::ULong>(enumval);\n";
00138 }
00139 {
00140 Function extraction("operator>>", "bool");
00141 extraction.addArg("strm", "Serializer&");
00142 extraction.addArg("enumval", cxx + "&");
00143 extraction.endArgs();
00144 be_global->impl_ <<
00145 " CORBA::ULong temp = 0;\n"
00146 " if (strm >> temp) {\n"
00147 " enumval = static_cast<" << cxx << ">(temp);\n"
00148 " return true;\n"
00149 " }\n"
00150 " return false;\n";
00151 }
00152 return true;
00153 }
00154
00155 namespace {
00156
00157 string getMaxSizeExprPrimitive(AST_Type* type)
00158 {
00159 if (type->node_type() != AST_Decl::NT_pre_defined) {
00160 return "";
00161 }
00162 AST_PredefinedType* pt = AST_PredefinedType::narrow_from_decl(type);
00163 switch (pt->pt()) {
00164 case AST_PredefinedType::PT_octet:
00165 return "max_marshaled_size_octet()";
00166 case AST_PredefinedType::PT_char:
00167 return "max_marshaled_size_char()";
00168 case AST_PredefinedType::PT_wchar:
00169 return "max_marshaled_size_wchar()";
00170 case AST_PredefinedType::PT_boolean:
00171 return "max_marshaled_size_boolean()";
00172 default:
00173 return "gen_max_marshaled_size(" + scoped(type->name()) + "())";
00174 }
00175 }
00176
00177 string getSerializerName(AST_Type* type)
00178 {
00179 switch (AST_PredefinedType::narrow_from_decl(type)->pt()) {
00180 case AST_PredefinedType::PT_long:
00181 return "long";
00182 case AST_PredefinedType::PT_ulong:
00183 return "ulong";
00184 case AST_PredefinedType::PT_short:
00185 return "short";
00186 case AST_PredefinedType::PT_ushort:
00187 return "ushort";
00188 case AST_PredefinedType::PT_octet:
00189 return "octet";
00190 case AST_PredefinedType::PT_char:
00191 return "char";
00192 case AST_PredefinedType::PT_wchar:
00193 return "wchar";
00194 case AST_PredefinedType::PT_float:
00195 return "float";
00196 case AST_PredefinedType::PT_double:
00197 return "double";
00198 case AST_PredefinedType::PT_longlong:
00199 return "longlong";
00200 case AST_PredefinedType::PT_ulonglong:
00201 return "ulonglong";
00202 case AST_PredefinedType::PT_longdouble:
00203 return "longdouble";
00204 case AST_PredefinedType::PT_boolean:
00205 return "boolean";
00206 default:
00207 return "";
00208 }
00209 }
00210
00211 string nameOfSeqHeader(AST_Type* elem)
00212 {
00213 string ser = getSerializerName(elem);
00214 if (ser.size()) {
00215 ser[0] = static_cast<char>(std::toupper(ser[0]));
00216 }
00217 if (ser[0] == 'U' || ser[0] == 'W') {
00218 ser[1] = static_cast<char>(std::toupper(ser[1]));
00219 }
00220 const size_t fourthLast = ser.size() - 4;
00221 if (ser.size() > 7 && ser.substr(fourthLast) == "long") {
00222 ser[fourthLast] = static_cast<char>(std::toupper(ser[fourthLast]));
00223 }
00224 if (ser == "Longdouble") return "LongDouble";
00225 return ser;
00226 }
00227
00228 string streamAndCheck(const string& expr, size_t indent = 2)
00229 {
00230 string idt(indent, ' ');
00231 return idt + "if (!(strm " + expr + ")) {\n" +
00232 idt + " return false;\n" +
00233 idt + "}\n";
00234 }
00235
00236 string checkAlignment(AST_Type* elem)
00237 {
00238
00239
00240 switch (AST_PredefinedType::narrow_from_decl(elem)->pt()) {
00241 case AST_PredefinedType::PT_longlong:
00242 case AST_PredefinedType::PT_ulonglong:
00243 case AST_PredefinedType::PT_double:
00244 case AST_PredefinedType::PT_longdouble:
00245 return
00246 " if ((size + padding) % 8) {\n"
00247 " padding += 4;\n"
00248 " }\n";
00249 default:
00250 return "";
00251 }
00252 }
00253
00254 bool isRtpsSpecialSequence(const string& cxx)
00255 {
00256 return cxx == "OpenDDS::RTPS::ParameterList";
00257 }
00258
00259 bool genRtpsSpecialSequence(const string& cxx)
00260 {
00261 {
00262 Function find_size("gen_find_size", "void");
00263 find_size.addArg("seq", "const " + cxx + "&");
00264 find_size.addArg("size", "size_t&");
00265 find_size.addArg("padding", "size_t&");
00266 find_size.endArgs();
00267 be_global->impl_ <<
00268 " for (CORBA::ULong i = 0; i < seq.length(); ++i) {\n"
00269 " if (seq[i]._d() == OpenDDS::RTPS::PID_SENTINEL) continue;\n"
00270 " size_t param_size = 0, param_padding = 0;\n"
00271 " gen_find_size(seq[i], param_size, param_padding);\n"
00272 " size += param_size + param_padding;\n"
00273 " if (size % 4) {\n"
00274 " size += 4 - (size % 4);\n"
00275 " }\n"
00276 " }\n"
00277 " size += 4; /* PID_SENTINEL */\n";
00278 }
00279 {
00280 Function insertion("operator<<", "bool");
00281 insertion.addArg("strm", "Serializer&");
00282 insertion.addArg("seq", "const " + cxx + "&");
00283 insertion.endArgs();
00284 be_global->impl_ <<
00285 " for (CORBA::ULong i = 0; i < seq.length(); ++i) {\n"
00286 " if (seq[i]._d() == OpenDDS::RTPS::PID_SENTINEL) continue;\n"
00287 " if (!(strm << seq[i])) {\n"
00288 " return false;\n"
00289 " }\n"
00290 " }\n"
00291 " return (strm << OpenDDS::RTPS::PID_SENTINEL)\n"
00292 " && (strm << OpenDDS::RTPS::PID_PAD);\n";
00293 }
00294 {
00295 Function extraction("operator>>", "bool");
00296 extraction.addArg("strm", "Serializer&");
00297 extraction.addArg("seq", cxx + "&");
00298 extraction.endArgs();
00299 be_global->impl_ <<
00300 " while (true) {\n"
00301 " const CORBA::ULong len = seq.length();\n"
00302 " seq.length(len + 1);\n"
00303 " if (!(strm >> seq[len])) {\n"
00304 " return false;\n"
00305 " }\n"
00306 " if (seq[len]._d() == OpenDDS::RTPS::PID_SENTINEL) {\n"
00307 " seq.length(len);\n"
00308 " return true;\n"
00309 " }\n"
00310 " }\n";
00311 }
00312 return true;
00313 }
00314
00315 bool isPropertySpecialSequence(const string& cxx)
00316 {
00317 return cxx == "DDS::PropertySeq"
00318 || cxx == "DDS::BinaryPropertySeq";
00319 }
00320
00321 bool genPropertySpecialSequence(const string& cxx)
00322 {
00323 {
00324 Function find_size("gen_find_size", "void");
00325 find_size.addArg("seq", "const " + cxx + "&");
00326 find_size.addArg("size", "size_t&");
00327 find_size.addArg("padding", "size_t&");
00328 find_size.endArgs();
00329 be_global->impl_ <<
00330 " find_size_ulong(size, padding);\n"
00331 " for (CORBA::ULong i = 0; i < seq.length(); ++i) {\n"
00332 " gen_find_size(seq[i], size, padding);\n"
00333 " }\n";
00334 }
00335 {
00336 Function insertion("operator<<", "bool");
00337 insertion.addArg("strm", "Serializer&");
00338 insertion.addArg("seq", "const " + cxx + "&");
00339 insertion.endArgs();
00340 be_global->impl_ <<
00341 " CORBA::ULong serlen = 0;\n"
00342 " for (CORBA::ULong i = 0; i < seq.length(); ++i) {\n"
00343 " if (seq[i].propagate) {\n"
00344 " ++serlen;\n"
00345 " }\n"
00346 " }\n"
00347 " if (!(strm << serlen)) {\n"
00348 " return false;\n"
00349 " }\n"
00350 " for (CORBA::ULong i = 0; i < seq.length(); ++i) {\n"
00351 " if (!(strm << seq[i])) {\n"
00352 " return false;\n"
00353 " }\n"
00354 " }\n"
00355 " return true;\n";
00356 }
00357 {
00358 Function extraction("operator>>", "bool");
00359 extraction.addArg("strm", "Serializer&");
00360 extraction.addArg("seq", cxx + "&");
00361 extraction.endArgs();
00362 be_global->impl_ <<
00363 " CORBA::ULong length;\n"
00364 " if (!(strm >> length)) {\n"
00365 " return false;\n"
00366 " }\n"
00367 " seq.length(length);\n"
00368 " for (CORBA::ULong i = 0; i < length; ++i) {\n"
00369 " if (!(strm >> seq[i])) {\n"
00370 " return false;\n"
00371 " }\n"
00372 " }\n"
00373 " return true;\n";
00374 }
00375 return true;
00376 }
00377
00378 void gen_sequence(UTL_ScopedName* tdname, AST_Sequence* seq)
00379 {
00380 be_global->add_include("dds/DCPS/Serializer.h");
00381 NamespaceGuard ng;
00382 string cxx = scoped(tdname);
00383
00384 for (size_t i = 0; i < LENGTH(special_sequences); ++i) {
00385 if (special_sequences[i].check(cxx)) {
00386 special_sequences[i].gen(cxx);
00387 return;
00388 }
00389 }
00390
00391 AST_Type* elem = resolveActualType(seq->base_type());
00392 Classification elem_cls = classify(elem);
00393 if (!elem->in_main_file()) {
00394 if (elem->node_type() == AST_Decl::NT_pre_defined) {
00395 if (be_global->language_mapping() != BE_GlobalData::LANGMAP_FACE_CXX &&
00396 be_global->language_mapping() != BE_GlobalData::LANGMAP_SP_CXX) {
00397 be_global->add_include(("dds/CorbaSeq/" + nameOfSeqHeader(elem)
00398 + "SeqTypeSupportImpl.h").c_str(), BE_GlobalData::STREAM_CPP);
00399 }
00400 } else {
00401 be_global->add_referenced(elem->file_name().c_str());
00402 }
00403 }
00404 string cxx_elem = scoped(elem->name());
00405 {
00406 Function find_size("gen_find_size", "void");
00407 find_size.addArg("seq", "const " + cxx + "&");
00408 find_size.addArg("size", "size_t&");
00409 find_size.addArg("padding", "size_t&");
00410 find_size.endArgs();
00411 be_global->impl_ <<
00412 " find_size_ulong(size, padding);\n"
00413 " if (seq.length() == 0) {\n"
00414 " return;\n"
00415 " }\n";
00416 if (elem_cls & CL_ENUM) {
00417 be_global->impl_ <<
00418 " size += seq.length() * max_marshaled_size_ulong();\n";
00419 } else if (elem_cls & CL_PRIMITIVE) {
00420 be_global->impl_ << checkAlignment(elem) <<
00421 " size += seq.length() * " << getMaxSizeExprPrimitive(elem) << ";\n";
00422 } else if (elem_cls & CL_INTERFACE) {
00423 be_global->impl_ <<
00424 " // sequence of objrefs is not marshaled\n";
00425 } else if (elem_cls == CL_UNKNOWN) {
00426 be_global->impl_ <<
00427 " // sequence of unknown/unsupported type\n";
00428 } else {
00429 be_global->impl_ <<
00430 " for (CORBA::ULong i = 0; i < seq.length(); ++i) {\n";
00431 if (elem_cls & CL_STRING) {
00432 be_global->impl_ <<
00433 " find_size_ulong(size, padding);\n"
00434 " if (seq[i]) {\n"
00435 " size += ACE_OS::strlen(seq[i])"
00436 << ((elem_cls & CL_WIDE)
00437 ? " * OpenDDS::DCPS::Serializer::WCHAR_SIZE;\n"
00438 : " + 1;\n") <<
00439 " }\n";
00440 } else if (elem_cls & CL_ARRAY) {
00441 be_global->impl_ <<
00442 " " << cxx_elem << "_var tmp_var = " << cxx_elem
00443 << "_dup(seq[i]);\n"
00444 " " << cxx_elem << "_forany tmp = tmp_var.inout();\n"
00445 " gen_find_size(tmp, size, padding);\n";
00446 } else {
00447 be_global->impl_ <<
00448 " gen_find_size(seq[i], size, padding);\n";
00449 }
00450 be_global->impl_ <<
00451 " }\n";
00452 }
00453 }
00454 {
00455 Function insertion("operator<<", "bool");
00456 insertion.addArg("strm", "Serializer&");
00457 insertion.addArg("seq", "const " + cxx + "&");
00458 insertion.endArgs();
00459 be_global->impl_ <<
00460 " const CORBA::ULong length = seq.length();\n"
00461 << streamAndCheck("<< length") <<
00462 " if (length == 0) {\n"
00463 " return true;\n"
00464 " }\n";
00465 if (elem_cls & CL_PRIMITIVE) {
00466 be_global->impl_ <<
00467 " return strm.write_" << getSerializerName(elem)
00468 << "_array(seq.get_buffer(), length);\n";
00469 } else if (elem_cls & CL_INTERFACE) {
00470 be_global->impl_ <<
00471 " return false; // sequence of objrefs is not marshaled\n";
00472 } else if (elem_cls == CL_UNKNOWN) {
00473 be_global->impl_ <<
00474 " return false; // sequence of unknown/unsupported type\n";
00475 } else {
00476 be_global->impl_ <<
00477 " for (CORBA::ULong i = 0; i < length; ++i) {\n";
00478 if (elem_cls & CL_ARRAY) {
00479 const string typedefname = scoped(seq->base_type()->name());
00480 be_global->impl_ <<
00481 " " << typedefname << "_var tmp_var = " << typedefname
00482 << "_dup(seq[i]);\n"
00483 " " << typedefname << "_forany tmp = tmp_var.inout();\n"
00484 << streamAndCheck("<< tmp", 4);
00485 } else {
00486 be_global->impl_ << streamAndCheck("<< seq[i]", 4);
00487 }
00488 be_global->impl_ <<
00489 " }\n"
00490 " return true;\n";
00491 }
00492 }
00493 {
00494 Function extraction("operator>>", "bool");
00495 extraction.addArg("strm", "Serializer&");
00496 extraction.addArg("seq", cxx + "&");
00497 extraction.endArgs();
00498 be_global->impl_ <<
00499 " CORBA::ULong length;\n"
00500 << streamAndCheck(">> length");
00501 if (!seq->unbounded()) {
00502 be_global->impl_ <<
00503 " if (length > seq.maximum()) {\n"
00504 " return false;\n"
00505 " }\n";
00506 }
00507 be_global->impl_ <<
00508 " seq.length(length);\n";
00509 if (elem_cls & CL_PRIMITIVE) {
00510 be_global->impl_ <<
00511 " if (length == 0) {\n"
00512 " return true;\n"
00513 " }\n"
00514 " return strm.read_" << getSerializerName(elem)
00515 << "_array(seq.get_buffer(), length);\n";
00516 } else if (elem_cls & CL_INTERFACE) {
00517 be_global->impl_ <<
00518 " return false; // sequence of objrefs is not marshaled\n";
00519 } else if (elem_cls == CL_UNKNOWN) {
00520 be_global->impl_ <<
00521 " return false; // sequence of unknown/unsupported type\n";
00522 } else {
00523 be_global->impl_ <<
00524 " for (CORBA::ULong i = 0; i < length; ++i) {\n";
00525 if (elem_cls & CL_ARRAY) {
00526 const string typedefname = scoped(seq->base_type()->name());
00527 be_global->impl_ <<
00528 " " << typedefname << "_var tmp = " << typedefname
00529 << "_alloc();\n"
00530 " " << typedefname << "_forany fa = tmp.inout();\n"
00531 << streamAndCheck(">> fa", 4) <<
00532 " " << typedefname << "_copy(seq[i], tmp.in());\n";
00533 } else if (elem_cls & CL_STRING) {
00534 if (elem_cls & CL_BOUNDED) {
00535 AST_String* str = AST_String::narrow_from_decl(elem);
00536 std::ostringstream args;
00537 args << "seq[i].out(), " << str->max_size()->ev()->u.ulval;
00538 be_global->impl_ <<
00539 streamAndCheck(">> " + getWrapper(args.str(), elem, WD_INPUT), 4);
00540 } else {
00541 const string getbuffer =
00542 (be_global->language_mapping() == BE_GlobalData::LANGMAP_NONE)
00543 ? ".get_buffer()" : "";
00544 be_global->impl_ << streamAndCheck(">> seq" + getbuffer + "[i]", 4);
00545 }
00546 } else {
00547 be_global->impl_ << streamAndCheck(">> seq[i]", 4);
00548 }
00549 be_global->impl_ <<
00550 " }\n"
00551 " return true;\n";
00552 }
00553 }
00554 }
00555
00556 string getAlignment(AST_Type* elem)
00557 {
00558 if (elem->node_type() == AST_Decl::NT_enum) {
00559 return "4";
00560 }
00561 switch (AST_PredefinedType::narrow_from_decl(elem)->pt()) {
00562 case AST_PredefinedType::PT_short:
00563 case AST_PredefinedType::PT_ushort:
00564 return "2";
00565 case AST_PredefinedType::PT_long:
00566 case AST_PredefinedType::PT_ulong:
00567 case AST_PredefinedType::PT_float:
00568 return "4";
00569 case AST_PredefinedType::PT_longlong:
00570 case AST_PredefinedType::PT_ulonglong:
00571 case AST_PredefinedType::PT_double:
00572 case AST_PredefinedType::PT_longdouble:
00573 return "8";
00574 default:
00575 return "";
00576 }
00577 }
00578
00579 void gen_array(UTL_ScopedName* name, AST_Array* arr)
00580 {
00581 be_global->add_include("dds/DCPS/Serializer.h");
00582 NamespaceGuard ng;
00583 string cxx = scoped(name);
00584 AST_Type* elem = resolveActualType(arr->base_type());
00585 Classification elem_cls = classify(elem);
00586 if (!elem->in_main_file()
00587 && elem->node_type() != AST_Decl::NT_pre_defined) {
00588 be_global->add_referenced(elem->file_name().c_str());
00589 }
00590 string cxx_elem = scoped(elem->name());
00591 size_t n_elems = 1;
00592 for (size_t i = 0; i < arr->n_dims(); ++i) {
00593 n_elems *= arr->dims()[i]->ev()->u.ulval;
00594 }
00595 {
00596 Function find_size("gen_find_size", "void");
00597 find_size.addArg("arr", "const " + cxx + "_forany&");
00598 find_size.addArg("size", "size_t&");
00599 find_size.addArg("padding", "size_t&");
00600 find_size.endArgs();
00601 if (elem_cls & CL_ENUM) {
00602 be_global->impl_ <<
00603 " find_size_ulong(size, padding);\n";
00604 if (n_elems > 1) {
00605 be_global->impl_ <<
00606 " size += " << n_elems - 1 << " * max_marshaled_size_ulong();\n";
00607 }
00608 } else if (elem_cls & CL_PRIMITIVE) {
00609 const string align = getAlignment(elem);
00610 if (!align.empty()) {
00611 be_global->impl_ <<
00612 " if ((size + padding) % " << align << ") {\n"
00613 " padding += " << align << " - ((size + padding) % " << align
00614 << ");\n"
00615 " }\n";
00616 }
00617 be_global->impl_ <<
00618 " size += " << n_elems << " * " << getMaxSizeExprPrimitive(elem)
00619 << ";\n";
00620 } else {
00621 string indent = " ";
00622 NestedForLoops nfl("CORBA::ULong", "i", arr, indent);
00623 if (elem_cls & CL_STRING) {
00624 be_global->impl_ <<
00625 indent << "find_size_ulong(size, padding);\n" <<
00626 indent << "size += ACE_OS::strlen(arr" << nfl.index_ << ".in())"
00627 << ((elem_cls & CL_WIDE)
00628 ? " * OpenDDS::DCPS::Serializer::WCHAR_SIZE;\n"
00629 : " + 1;\n");
00630 } else if (elem_cls & CL_ARRAY) {
00631 be_global->impl_ <<
00632 indent << cxx_elem << "_var tmp_var = " << cxx_elem
00633 << "_dup(arr" << nfl.index_ << ");\n" <<
00634 indent << cxx_elem << "_forany tmp = tmp_var.inout();\n" <<
00635 indent << "gen_find_size(tmp, size, padding);\n";
00636 } else {
00637 be_global->impl_ <<
00638 indent << "gen_find_size(arr" << nfl.index_
00639 << ", size, padding);\n";
00640 }
00641 }
00642 }
00643 {
00644 Function insertion("operator<<", "bool");
00645 insertion.addArg("strm", "Serializer&");
00646 insertion.addArg("arr", "const " + cxx + "_forany&");
00647 insertion.endArgs();
00648 if (elem_cls & CL_PRIMITIVE) {
00649 string suffix;
00650 for (unsigned int i = 1; i < arr->n_dims(); ++i)
00651 suffix += "[0]";
00652 be_global->impl_ <<
00653 " return strm.write_" << getSerializerName(elem)
00654 << "_array(arr.in()" << suffix << ", " << n_elems << ");\n";
00655 } else {
00656 {
00657 string indent = " ";
00658 NestedForLoops nfl("CORBA::ULong", "i", arr, indent);
00659 if (elem_cls & CL_ARRAY) {
00660 be_global->impl_ <<
00661 indent << cxx_elem << "_var tmp_var = " << cxx_elem
00662 << "_dup(arr" << nfl.index_ << ");\n" <<
00663 indent << cxx_elem << "_forany tmp = tmp_var.inout();\n" <<
00664 streamAndCheck("<< tmp", indent.size());
00665 } else {
00666 string suffix = (elem_cls & CL_STRING) ? ".in()" : "";
00667 be_global->impl_ <<
00668 streamAndCheck("<< arr" + nfl.index_ + suffix , indent.size());
00669 }
00670 }
00671 be_global->impl_ << " return true;\n";
00672 }
00673 }
00674 {
00675 Function extraction("operator>>", "bool");
00676 extraction.addArg("strm", "Serializer&");
00677 extraction.addArg("arr", cxx + "_forany&");
00678 extraction.endArgs();
00679 if (elem_cls & CL_PRIMITIVE) {
00680 string suffix;
00681 for (unsigned int i = 1; i < arr->n_dims(); ++i)
00682 suffix += "[0]";
00683 be_global->impl_ <<
00684 " return strm.read_" << getSerializerName(elem)
00685 << "_array(arr.out()" << suffix << ", " << n_elems << ");\n";
00686 } else {
00687 {
00688 string indent = " ";
00689 NestedForLoops nfl("CORBA::ULong", "i", arr, indent);
00690 if (elem_cls & CL_ARRAY) {
00691 const string typedefname = scoped(arr->base_type()->name());
00692 be_global->impl_ <<
00693 indent << typedefname << "_var tmp = " << typedefname
00694 << "_alloc();\n" <<
00695 indent << typedefname << "_forany fa = tmp.inout();\n"
00696 << streamAndCheck(">> fa", indent.size()) <<
00697 indent << typedefname << "_copy(arr" << nfl.index_ <<
00698 ", tmp.in());\n";
00699 } else {
00700 string suffix = (elem_cls & CL_STRING) ? ".out()" : "";
00701 be_global->impl_ <<
00702 streamAndCheck(">> arr" + nfl.index_ + suffix, indent.size());
00703 }
00704 }
00705 be_global->impl_ << " return true;\n";
00706 }
00707 }
00708 }
00709
00710 string getArrayForany(const char* prefix, const char* fname,
00711 const string& cxx_fld)
00712 {
00713 string local = fname;
00714 if (local.size() > 2 && local.substr(local.size() - 2, 2) == "()") {
00715 local.erase(local.size() - 2);
00716 }
00717 return cxx_fld + "_forany " + prefix + '_' + local + "(const_cast<"
00718 + cxx_fld + "_slice*>(" + prefix + "." + fname + "));";
00719 }
00720
00721
00722
00723
00724
00725 AST_Type* find_type(const std::vector<AST_Field*>& fields, const string& key)
00726 {
00727 string key_base = key;
00728 string key_rem;
00729 bool is_array = false;
00730 size_t pos = key.find_first_of(".[");
00731 if (pos != string::npos) {
00732 key_base = key.substr(0, pos);
00733 if (key[pos] == '[') {
00734 is_array = true;
00735 size_t l_brack = key.find("]");
00736 if (l_brack == string::npos) {
00737 throw string("Missing right bracket");
00738 } else if (l_brack != key.length()) {
00739 key_rem = key.substr(l_brack+1);
00740 }
00741 } else {
00742 key_rem = key.substr(pos+1);
00743 }
00744 }
00745 for (size_t i = 0; i < fields.size(); ++i) {
00746 string field_name = fields[i]->local_name()->get_string();
00747 if (field_name == key_base) {
00748 AST_Type* field_type = fields[i]->field_type();
00749 if (!is_array && key_rem.empty()) {
00750
00751
00752
00753 AST_Structure* sub_struct = dynamic_cast<AST_Structure*>(field_type);
00754 if (sub_struct != 0) {
00755 throw string("Structs not allowed as keys");
00756 }
00757 AST_Typedef* typedef_node = dynamic_cast<AST_Typedef*>(field_type);
00758 if (typedef_node != 0) {
00759 AST_Array* array_node =
00760 dynamic_cast<AST_Array*>(typedef_node->base_type());
00761 if (array_node != 0) {
00762 throw string("Arrays not allowed as keys");
00763 }
00764 }
00765 return field_type;
00766 } else if (is_array) {
00767
00768 AST_Typedef* typedef_node = dynamic_cast<AST_Typedef*>(field_type);
00769 if (typedef_node == 0) {
00770 throw string("Indexing for non-array type");
00771 }
00772 AST_Array* array_node =
00773 dynamic_cast<AST_Array*>(typedef_node->base_type());
00774 if (array_node == 0) {
00775 throw string("Indexing for non-array type");
00776 }
00777 if (array_node->n_dims() > 1) {
00778 throw string("Only single dimension arrays allowed in keys");
00779 }
00780 if (key_rem == "") {
00781 return array_node->base_type();
00782 } else {
00783
00784 if ((key_rem[0] != '.') || (key_rem.length() == 1)) {
00785 throw string("Unexpected characters after array index");
00786 } else {
00787
00788
00789 key_rem = key_rem.substr(1);
00790 field_type = array_node->base_type();
00791 }
00792 }
00793 }
00794
00795
00796 AST_Structure* sub_struct = dynamic_cast<AST_Structure*>(field_type);
00797 if (sub_struct == 0) {
00798 throw string("Expected structure field for ") + key_base;
00799 }
00800 size_t nfields = sub_struct->nfields();
00801 std::vector<AST_Field*> sub_fields;
00802 sub_fields.reserve(nfields);
00803
00804 for (unsigned long i = 0; i < nfields; ++i) {
00805 AST_Field** f;
00806 sub_struct->field(f, i);
00807 sub_fields.push_back(*f);
00808 }
00809
00810 return find_type(sub_fields, key_rem);
00811 }
00812 }
00813 throw string("Field not found.");
00814 }
00815
00816 bool is_bounded_type(AST_Type* type)
00817 {
00818 bool bounded = true;
00819 static std::vector<AST_Type*> type_stack;
00820 type = resolveActualType(type);
00821 for (unsigned int i = 0; i < type_stack.size(); i++) {
00822
00823 if (type == type_stack[i]) return false;
00824 }
00825 type_stack.push_back(type);
00826 Classification fld_cls = classify(type);
00827 if ((fld_cls & CL_STRING) && !(fld_cls & CL_BOUNDED)) {
00828 bounded = false;
00829 } else if (fld_cls & CL_STRUCTURE) {
00830 AST_Structure* struct_node = dynamic_cast<AST_Structure*>(type);
00831 for (unsigned long i = 0; i < struct_node->nfields(); ++i) {
00832 AST_Field** f;
00833 struct_node->field(f, i);
00834 if (!is_bounded_type((*f)->field_type())) {
00835 bounded = false;
00836 break;
00837 }
00838 }
00839 } else if (fld_cls & CL_SEQUENCE) {
00840 if (fld_cls & CL_BOUNDED) {
00841 AST_Sequence* seq_node = dynamic_cast<AST_Sequence*>(type);
00842 if (!is_bounded_type(seq_node->base_type())) bounded = false;
00843 } else {
00844 bounded = false;
00845 }
00846 } else if (fld_cls & CL_ARRAY) {
00847 AST_Array* array_node = dynamic_cast<AST_Array*>(type);
00848 if (!is_bounded_type(array_node->base_type())) bounded = false;
00849 } else if (fld_cls & CL_UNION) {
00850 AST_Union* union_node = dynamic_cast<AST_Union*>(type);
00851 for (unsigned long i = 0; i < union_node->nfields(); ++i) {
00852 AST_Field** f;
00853 union_node->field(f, i);
00854 if (!is_bounded_type((*f)->field_type())) {
00855 bounded = false;
00856 break;
00857 }
00858 }
00859 }
00860 type_stack.pop_back();
00861 return bounded;
00862 }
00863
00864 void align(size_t alignment, size_t& size, size_t& padding)
00865 {
00866 if ((size + padding) % alignment) {
00867 padding += alignment - ((size + padding) % alignment);
00868 }
00869 }
00870
00871 void max_marshaled_size(AST_Type* type, size_t& size, size_t& padding);
00872
00873
00874
00875 void mms_repeating(AST_Type* type, size_t n, size_t& size, size_t& padding)
00876 {
00877 if (n > 0) {
00878
00879 max_marshaled_size(type, size, padding);
00880 }
00881 if (n > 1) {
00882
00883 size_t prev_size = size, prev_pad = padding;
00884 max_marshaled_size(type, size, padding);
00885 size += (n - 2) * (size - prev_size);
00886 padding += (n - 2) * (padding - prev_pad);
00887 }
00888 }
00889
00890
00891 void max_marshaled_size(AST_Type* type, size_t& size, size_t& padding)
00892 {
00893 type = resolveActualType(type);
00894 switch (type->node_type()) {
00895 case AST_Decl::NT_pre_defined: {
00896 AST_PredefinedType* p = AST_PredefinedType::narrow_from_decl(type);
00897 switch (p->pt()) {
00898 case AST_PredefinedType::PT_char:
00899 case AST_PredefinedType::PT_boolean:
00900 case AST_PredefinedType::PT_octet:
00901 size += 1;
00902 break;
00903 case AST_PredefinedType::PT_short:
00904 case AST_PredefinedType::PT_ushort:
00905 align(2, size, padding);
00906 size += 2;
00907 break;
00908 case AST_PredefinedType::PT_wchar:
00909 size += 3;
00910 break;
00911 case AST_PredefinedType::PT_long:
00912 case AST_PredefinedType::PT_ulong:
00913 case AST_PredefinedType::PT_float:
00914 align(4, size, padding);
00915 size += 4;
00916 break;
00917 case AST_PredefinedType::PT_longlong:
00918 case AST_PredefinedType::PT_ulonglong:
00919 case AST_PredefinedType::PT_double:
00920 align(8, size, padding);
00921 size += 8;
00922 break;
00923 case AST_PredefinedType::PT_longdouble:
00924 align(8, size, padding);
00925 size += 16;
00926 break;
00927 default:
00928
00929 break;
00930 }
00931 break;
00932 }
00933 case AST_Decl::NT_enum:
00934 align(4, size, padding);
00935 size += 4;
00936 break;
00937 case AST_Decl::NT_string:
00938 case AST_Decl::NT_wstring: {
00939 AST_String* string_node = dynamic_cast<AST_String*>(type);
00940 align(4, size, padding);
00941 size += 4;
00942 const int width = (string_node->width() == 1) ? 1 : 2 ;
00943 size += width * string_node->max_size()->ev()->u.ulval;
00944 if (type->node_type() == AST_Decl::NT_string) {
00945 size += 1;
00946 }
00947 break;
00948 }
00949 case AST_Decl::NT_struct: {
00950 AST_Structure* struct_node = dynamic_cast<AST_Structure*>(type);
00951 for (unsigned long i = 0; i < struct_node->nfields(); ++i) {
00952 AST_Field** f;
00953 struct_node->field(f, i);
00954 AST_Type* field_type = (*f)->field_type();
00955 max_marshaled_size(field_type, size, padding);
00956 }
00957 break;
00958 }
00959 case AST_Decl::NT_sequence: {
00960 AST_Sequence* seq_node = dynamic_cast<AST_Sequence*>(type);
00961 AST_Type* base_node = seq_node->base_type();
00962 size_t bound = seq_node->max_size()->ev()->u.ulval;
00963 align(4, size, padding);
00964 size += 4;
00965 mms_repeating(base_node, bound, size, padding);
00966 break;
00967 }
00968 case AST_Decl::NT_array: {
00969 AST_Array* array_node = dynamic_cast<AST_Array*>(type);
00970 AST_Type* base_node = array_node->base_type();
00971 size_t array_size = 1;
00972 AST_Expression** dims = array_node->dims();
00973 for (unsigned long i = 0; i < array_node->n_dims(); i++) {
00974 array_size *= dims[i]->ev()->u.ulval;
00975 }
00976 mms_repeating(base_node, array_size, size, padding);
00977 break;
00978 }
00979 case AST_Decl::NT_union: {
00980 AST_Union* union_node = dynamic_cast<AST_Union*>(type);
00981 max_marshaled_size(union_node->disc_type(), size, padding);
00982 size_t largest_field_size = 0, largest_field_pad = 0;
00983 const size_t starting_size = size, starting_pad = padding;
00984 for (unsigned long i = 0; i < union_node->nfields(); ++i) {
00985 AST_Field** f;
00986 union_node->field(f, i);
00987 AST_Type* field_type = (*f)->field_type();
00988 max_marshaled_size(field_type, size, padding);
00989 size_t field_size = size - starting_size,
00990 field_pad = padding - starting_pad;
00991 if (field_size > largest_field_size) {
00992 largest_field_size = field_size;
00993 largest_field_pad = field_pad;
00994 }
00995
00996 size = starting_size;
00997 padding = starting_pad;
00998 }
00999 size += largest_field_size;
01000 padding += largest_field_pad;
01001 break;
01002 }
01003 default:
01004
01005 break;
01006 }
01007 }
01008 }
01009
01010 bool marshal_generator::gen_typedef(AST_Typedef*, UTL_ScopedName* name, AST_Type* base,
01011 const char*)
01012 {
01013 switch (base->node_type()) {
01014 case AST_Decl::NT_sequence:
01015 gen_sequence(name, AST_Sequence::narrow_from_decl(base));
01016 break;
01017 case AST_Decl::NT_array:
01018 gen_array(name, AST_Array::narrow_from_decl(base));
01019 break;
01020 default:
01021 return true;
01022 }
01023 return true;
01024 }
01025
01026 namespace {
01027
01028 string findSizeCommon(const string& name, AST_Type* type,
01029 const string& prefix, string& intro,
01030 const string& = "")
01031 {
01032 AST_Type* typedeff = type;
01033 type = resolveActualType(type);
01034 Classification fld_cls = classify(type);
01035 const string qual = prefix + '.' + name;
01036 const string indent = (prefix == "uni") ? " " : " ";
01037 if (fld_cls & CL_ENUM) {
01038 return indent + "find_size_ulong(size, padding);\n";
01039 } else if (fld_cls & CL_STRING) {
01040 const string suffix = (prefix == "uni") ? "" : ".in()";
01041 return indent + "find_size_ulong(size, padding);\n" +
01042 indent + "size += ACE_OS::strlen(" + qual + suffix + ")"
01043 + ((fld_cls & CL_WIDE) ? " * OpenDDS::DCPS::Serializer::WCHAR_SIZE;\n"
01044 : " + 1;\n");
01045 } else if (fld_cls & CL_PRIMITIVE) {
01046 string align = getAlignment(type);
01047 if (!align.empty()) {
01048 align =
01049 indent + "if ((size + padding) % " + align + ") {\n" +
01050 indent + " padding += " + align + " - ((size + padding) % "
01051 + align + ");\n" +
01052 indent + "}\n";
01053 }
01054 return align +
01055 indent + "size += gen_max_marshaled_size(" +
01056 getWrapper(qual, type, WD_OUTPUT) + ");\n";
01057 } else if (fld_cls == CL_UNKNOWN) {
01058 return "";
01059 } else {
01060 string fieldref = prefix, local = name;
01061 if (fld_cls & CL_ARRAY) {
01062 intro += " " + getArrayForany(prefix.c_str(), name.c_str(),
01063 scoped(typedeff->name())) + '\n';
01064 fieldref += '_';
01065 if (local.size() > 2 && local.substr(local.size() - 2) == "()") {
01066 local.erase(local.size() - 2);
01067 }
01068 } else {
01069 fieldref += '.';
01070 }
01071 return indent +
01072 "gen_find_size(" + fieldref + local + ", size, padding);\n";
01073 }
01074 }
01075
01076
01077 string streamCommon(const string& name, AST_Type* type,
01078 const string& prefix, string& intro,
01079 const string& stru = "")
01080 {
01081 AST_Type* typedeff = type;
01082 type = resolveActualType(type);
01083 Classification fld_cls = classify(type);
01084 const string qual = prefix + '.' + name, shift = prefix.substr(0, 2);
01085 WrapDirection dir = (shift == ">>") ? WD_INPUT : WD_OUTPUT;
01086 if ((fld_cls & CL_STRING) && (dir == WD_INPUT)) {
01087 return "(strm " + qual + ".out())";
01088 } else if (fld_cls & CL_PRIMITIVE) {
01089 return "(strm " + shift + ' '
01090 + getWrapper(qual.substr(3), type, dir) + ')';
01091 } else if (fld_cls == CL_UNKNOWN) {
01092 if (dir == WD_INPUT) {
01093 std::cerr << "WARNING: field " << name << " can not be serialized. "
01094 "The struct or union it belongs to (" << stru <<
01095 ") can not be used in an OpenDDS topic type." << std::endl;
01096 }
01097 return "false";
01098 } else {
01099 string fieldref = prefix, local = name;
01100 const bool accessor =
01101 local.size() > 2 && local.substr(local.size() - 2) == "()";
01102 if (fld_cls & CL_ARRAY) {
01103 string pre = prefix;
01104 if (shift == ">>" || shift == "<<") {
01105 pre.erase(0, 3);
01106 }
01107 if (accessor) {
01108 local.erase(local.size() - 2);
01109 }
01110 intro += " " + getArrayForany(pre.c_str(), name.c_str(),
01111 scoped(typedeff->name())) + '\n';
01112 fieldref += '_';
01113 } else {
01114 fieldref += '.';
01115 }
01116 if ((fld_cls & CL_STRING) && !accessor) local += ".in()";
01117 return "(strm " + fieldref + local + ')';
01118 }
01119 }
01120
01121 bool isBinaryProperty_t(const string& cxx)
01122 {
01123 return cxx == "DDS::BinaryProperty_t";
01124 }
01125
01126 bool genBinaryProperty_t(const string& cxx)
01127 {
01128 {
01129 Function find_size("gen_find_size", "void");
01130 find_size.addArg("stru", "const " + cxx + "&");
01131 find_size.addArg("size", "size_t&");
01132 find_size.addArg("padding", "size_t&");
01133 find_size.endArgs();
01134 be_global->impl_ <<
01135 " if (stru.propagate) {\n"
01136 " find_size_ulong(size, padding);\n"
01137 " size += ACE_OS::strlen(stru.name.in()) + 1;\n"
01138 " gen_find_size(stru.value, size, padding);\n"
01139 " }\n";
01140 }
01141 {
01142 Function insertion("operator<<", "bool");
01143 insertion.addArg("strm", "Serializer&");
01144 insertion.addArg("stru", "const " + cxx + "&");
01145 insertion.endArgs();
01146 be_global->impl_ <<
01147 " if (stru.propagate) {\n"
01148 " return (strm << stru.name.in()) && (strm << stru.value);\n"
01149 " }\n"
01150 " return true;\n";
01151 }
01152 {
01153 Function extraction("operator>>", "bool");
01154 extraction.addArg("strm", "Serializer&");
01155 extraction.addArg("stru", cxx + "&");
01156 extraction.endArgs();
01157 be_global->impl_ <<
01158 " stru.propagate = true;\n"
01159 " return (strm >> stru.name.out()) && (strm >> stru.value);\n";
01160 }
01161 return true;
01162 }
01163
01164 bool isProperty_t(const string& cxx)
01165 {
01166 return cxx == "DDS::Property_t";
01167 }
01168
01169 bool genProperty_t(const string& cxx)
01170 {
01171 {
01172 Function find_size("gen_find_size", "void");
01173 find_size.addArg("stru", "const " + cxx + "&");
01174 find_size.addArg("size", "size_t&");
01175 find_size.addArg("padding", "size_t&");
01176 find_size.endArgs();
01177 be_global->impl_ <<
01178 " if (stru.propagate) {\n"
01179 " find_size_ulong(size, padding);\n"
01180 " size += ACE_OS::strlen(stru.name.in()) + 1;\n"
01181 " find_size_ulong(size, padding);\n"
01182 " size += ACE_OS::strlen(stru.value.in()) + 1;\n"
01183 " }\n";
01184 }
01185 {
01186 Function insertion("operator<<", "bool");
01187 insertion.addArg("strm", "Serializer&");
01188 insertion.addArg("stru", "const " + cxx + "&");
01189 insertion.endArgs();
01190 be_global->impl_ <<
01191 " if (stru.propagate) {\n"
01192 " return (strm << stru.name.in()) && (strm << stru.value.in());\n"
01193 " }\n"
01194 " return true;\n";
01195 }
01196 {
01197 Function extraction("operator>>", "bool");
01198 extraction.addArg("strm", "Serializer&");
01199 extraction.addArg("stru", cxx + "&");
01200 extraction.endArgs();
01201 be_global->impl_ <<
01202 " stru.propagate = true;\n"
01203 " return (strm >> stru.name.out()) && (strm >> stru.value.out());\n";
01204 }
01205 return true;
01206 }
01207
01208 bool isPropertyQosPolicy(const string& cxx)
01209 {
01210 return cxx == "DDS::PropertyQosPolicy";
01211 }
01212
01213 bool genPropertyQosPolicy(const string& cxx)
01214 {
01215 {
01216 Function find_size("gen_find_size", "void");
01217 find_size.addArg("stru", "const " + cxx + "&");
01218 find_size.addArg("size", "size_t&");
01219 find_size.addArg("padding", "size_t&");
01220 find_size.endArgs();
01221 be_global->impl_ <<
01222 " gen_find_size(stru.value, size, padding);\n"
01223 " gen_find_size(stru.binary_value, size, padding);\n";
01224 }
01225 {
01226 Function insertion("operator<<", "bool");
01227 insertion.addArg("strm", "Serializer&");
01228 insertion.addArg("stru", "const " + cxx + "&");
01229 insertion.endArgs();
01230 be_global->impl_ <<
01231 " return (strm << stru.value)\n"
01232 " && (strm << stru.binary_value);\n";
01233 }
01234 {
01235 Function extraction("operator>>", "bool");
01236 extraction.addArg("strm", "Serializer&");
01237 extraction.addArg("stru", cxx + "&");
01238 extraction.endArgs();
01239 be_global->impl_ <<
01240 " if (!(strm >> stru.value)) {\n"
01241 " return false;\n"
01242 " }\n"
01243 " if (!strm.length() || !strm.skip(0, 4) || !strm.length()) {\n"
01244 " return true; // optional member missing\n"
01245 " }\n"
01246 " return strm >> stru.binary_value;\n";
01247 }
01248 return true;
01249 }
01250
01251 bool isSecuritySubmessage(const string& cxx)
01252 {
01253 return cxx == "OpenDDS::RTPS::SecuritySubmessage";
01254 }
01255
01256 bool genSecuritySubmessage(const string& cxx)
01257 {
01258 {
01259 Function find_size("gen_find_size", "void");
01260 find_size.addArg("stru", "const " + cxx + "&");
01261 find_size.addArg("size", "size_t&");
01262 find_size.addArg("padding", "size_t&");
01263 find_size.endArgs();
01264 be_global->impl_ <<
01265 " gen_find_size(stru.smHeader, size, padding);\n"
01266 " size += stru.content.length() * max_marshaled_size_octet();\n";
01267 }
01268 {
01269 Function insertion("operator<<", "bool");
01270 insertion.addArg("strm", "Serializer&");
01271 insertion.addArg("stru", "const " + cxx + "&");
01272 insertion.endArgs();
01273 be_global->impl_ <<
01274 " return (strm << stru.smHeader)\n"
01275 " && strm.write_octet_array(stru.content.get_buffer(), "
01276 "stru.content.length());\n";
01277 }
01278 {
01279 Function extraction("operator>>", "bool");
01280 extraction.addArg("strm", "Serializer&");
01281 extraction.addArg("stru", cxx + "&");
01282 extraction.endArgs();
01283 be_global->impl_ <<
01284 " if (strm >> stru.smHeader) {\n"
01285 " stru.content.length(stru.smHeader.submessageLength);\n"
01286 " if (strm.read_octet_array(stru.content.get_buffer(),\n"
01287 " stru.smHeader.submessageLength)) {\n"
01288 " return true;\n"
01289 " }\n"
01290 " }\n"
01291 " return false;\n";
01292 }
01293 return true;
01294 }
01295
01296 bool isRtpsSpecialStruct(const string& cxx)
01297 {
01298 return cxx == "OpenDDS::RTPS::SequenceNumberSet"
01299 || cxx == "OpenDDS::RTPS::FragmentNumberSet";
01300 }
01301
01302 bool genRtpsSpecialStruct(const string& cxx)
01303 {
01304 {
01305 Function find_size("gen_find_size", "void");
01306 find_size.addArg("stru", "const " + cxx + "&");
01307 find_size.addArg("size", "size_t&");
01308 find_size.addArg("padding", "size_t&");
01309 find_size.endArgs();
01310 be_global->impl_ <<
01311 " size += "
01312 << ((cxx == "OpenDDS::RTPS::SequenceNumberSet") ? "12" : "8")
01313 << " + 4 * ((stru.numBits + 31) / 32); // RTPS Custom\n";
01314 }
01315 {
01316 Function insertion("operator<<", "bool");
01317 insertion.addArg("strm", "Serializer&");
01318 insertion.addArg("stru", "const " + cxx + "&");
01319 insertion.endArgs();
01320 be_global->impl_ <<
01321 " if ((strm << stru.bitmapBase) && (strm << stru.numBits)) {\n"
01322 " const CORBA::ULong M = (stru.numBits + 31) / 32;\n"
01323 " if (stru.bitmap.length() < M) {\n"
01324 " return false;\n"
01325 " }\n"
01326 " for (CORBA::ULong i = 0; i < M; ++i) {\n"
01327 " if (!(strm << stru.bitmap[i])) {\n"
01328 " return false;\n"
01329 " }\n"
01330 " }\n"
01331 " return true;\n"
01332 " }\n"
01333 " return false;\n";
01334 }
01335 {
01336 Function extraction("operator>>", "bool");
01337 extraction.addArg("strm", "Serializer&");
01338 extraction.addArg("stru", cxx + "&");
01339 extraction.endArgs();
01340 be_global->impl_ <<
01341 " if ((strm >> stru.bitmapBase) && (strm >> stru.numBits)) {\n"
01342 " const CORBA::ULong M = (stru.numBits + 31) / 32;\n"
01343 " if (M > 8) {\n"
01344 " return false;\n"
01345 " }\n"
01346 " stru.bitmap.length(M);\n"
01347 " for (CORBA::ULong i = 0; i < M; ++i) {\n"
01348 " if (!(strm >> stru.bitmap[i])) {\n"
01349 " return false;\n"
01350 " }\n"
01351 " }\n"
01352 " return true;\n"
01353 " }\n"
01354 " return false;\n";
01355 }
01356 return true;
01357 }
01358
01359 struct RtpsFieldCustomizer {
01360
01361 explicit RtpsFieldCustomizer(const string& cxx)
01362 {
01363 if (cxx == "OpenDDS::RTPS::DataSubmessage") {
01364 cst_["inlineQos"] = "stru.smHeader.flags & 2";
01365 iQosOffset_ = "16";
01366
01367 } else if (cxx == "OpenDDS::RTPS::DataFragSubmessage") {
01368 cst_["inlineQos"] = "stru.smHeader.flags & 2";
01369 iQosOffset_ = "28";
01370
01371 } else if (cxx == "OpenDDS::RTPS::InfoReplySubmessage") {
01372 cst_["multicastLocatorList"] = "stru.smHeader.flags & 2";
01373
01374 } else if (cxx == "OpenDDS::RTPS::InfoTimestampSubmessage") {
01375 cst_["timestamp"] = "!(stru.smHeader.flags & 2)";
01376
01377 } else if (cxx == "OpenDDS::RTPS::InfoReplyIp4Submessage") {
01378 cst_["multicastLocator"] = "stru.smHeader.flags & 2";
01379
01380 } else if (cxx == "OpenDDS::RTPS::SubmessageHeader") {
01381 preamble_ =
01382 " strm.swap_bytes(ACE_CDR_BYTE_ORDER != (stru.flags & 1));\n";
01383 }
01384 }
01385
01386 string getConditional(const string& field_name) const
01387 {
01388 if (cst_.empty()) {
01389 return "";
01390 }
01391 std::map<string, string>::const_iterator it = cst_.find(field_name);
01392 if (it != cst_.end()) {
01393 return it->second;
01394 }
01395 return "";
01396 }
01397
01398 string preFieldRead(const string& field_name) const
01399 {
01400 if (cst_.empty() || field_name != "inlineQos" || iQosOffset_.empty()) {
01401 return "";
01402 }
01403 return "strm.skip(stru.octetsToInlineQos - " + iQosOffset_ + ")\n"
01404 " && ";
01405 }
01406
01407 std::map<string, string> cst_;
01408 string iQosOffset_, preamble_;
01409 };
01410 }
01411
01412 bool marshal_generator::gen_struct(AST_Structure* ,
01413 UTL_ScopedName* name,
01414 const std::vector<AST_Field*>& fields,
01415 AST_Type::SIZE_TYPE ,
01416 const char* )
01417 {
01418 NamespaceGuard ng;
01419 be_global->add_include("dds/DCPS/Serializer.h");
01420 string cxx = scoped(name);
01421
01422 for (size_t i = 0; i < LENGTH(special_structs); ++i) {
01423 if (special_structs[i].check(cxx)) {
01424 return special_structs[i].gen(cxx);
01425 }
01426 }
01427
01428 RtpsFieldCustomizer rtpsCustom(cxx);
01429 {
01430 Function find_size("gen_find_size", "void");
01431 find_size.addArg("stru", "const " + cxx + "&");
01432 find_size.addArg("size", "size_t&");
01433 find_size.addArg("padding", "size_t&");
01434 find_size.endArgs();
01435 string expr, intro;
01436 for (size_t i = 0; i < fields.size(); ++i) {
01437 AST_Type* field_type = resolveActualType(fields[i]->field_type());
01438 if (!field_type->in_main_file()
01439 && field_type->node_type() != AST_Decl::NT_pre_defined) {
01440 be_global->add_referenced(field_type->file_name().c_str());
01441 }
01442 const string field_name = fields[i]->local_name()->get_string(),
01443 cond = rtpsCustom.getConditional(field_name);
01444 if (!cond.empty()) {
01445 expr += " if (" + cond + ") {\n ";
01446 }
01447 expr += findSizeCommon(field_name, field_type, "stru", intro);
01448 if (!cond.empty()) {
01449 expr += " }\n";
01450 }
01451 }
01452 be_global->impl_ << intro << expr;
01453 }
01454 {
01455 Function insertion("operator<<", "bool");
01456 insertion.addArg("strm", "Serializer&");
01457 insertion.addArg("stru", "const " + cxx + "&");
01458 insertion.endArgs();
01459 string expr, intro = rtpsCustom.preamble_;
01460 for (size_t i = 0; i < fields.size(); ++i) {
01461 if (i) expr += "\n && ";
01462 const string field_name = fields[i]->local_name()->get_string(),
01463 cond = rtpsCustom.getConditional(field_name);
01464 if (!cond.empty()) {
01465 expr += "(!(" + cond + ") || ";
01466 }
01467 expr += streamCommon(field_name, fields[i]->field_type(),
01468 "<< stru", intro, cxx);
01469 if (!cond.empty()) {
01470 expr += ")";
01471 }
01472 }
01473 be_global->impl_ << intro << " return " << expr << ";\n";
01474 }
01475 {
01476 Function extraction("operator>>", "bool");
01477 extraction.addArg("strm", "Serializer&");
01478 extraction.addArg("stru", cxx + "&");
01479 extraction.endArgs();
01480 string expr, intro;
01481 for (size_t i = 0; i < fields.size(); ++i) {
01482 if (i) expr += "\n && ";
01483 const string field_name = fields[i]->local_name()->get_string(),
01484 cond = rtpsCustom.getConditional(field_name);
01485 if (!cond.empty()) {
01486 expr += rtpsCustom.preFieldRead(field_name);
01487 expr += "(!(" + cond + ") || ";
01488 }
01489 expr += streamCommon(field_name, fields[i]->field_type(),
01490 ">> stru", intro, cxx);
01491 if (!cond.empty()) {
01492 expr += ")";
01493 }
01494 }
01495 be_global->impl_ << intro << " return " << expr << ";\n";
01496 }
01497
01498 IDL_GlobalData::DCPS_Data_Type_Info* info = idl_global->is_dcps_type(name);
01499
01500 if (info != 0) {
01501 bool is_bounded_struct = true;
01502 for (size_t i = 0; i < fields.size(); ++i) {
01503 if (!is_bounded_type(fields[i]->field_type())) {
01504 is_bounded_struct = false;
01505 break;
01506 }
01507 }
01508 {
01509 Function max_marsh("gen_max_marshaled_size", "size_t");
01510 max_marsh.addArg("stru", "const " + cxx + "&");
01511 max_marsh.addArg("align", "bool");
01512 max_marsh.endArgs();
01513 if (is_bounded_struct) {
01514 size_t size = 0, padding = 0;
01515 for (size_t i = 0; i < fields.size(); ++i) {
01516 max_marshaled_size(fields[i]->field_type(), size, padding);
01517 }
01518 if (padding) {
01519 be_global->impl_
01520 << " return align ? " << size + padding << " : " << size << ";\n";
01521 } else {
01522 be_global->impl_
01523 << " return " << size << ";\n";
01524 }
01525 } else {
01526 be_global->impl_
01527 << " return 0;\n";
01528 }
01529 }
01530
01531
01532 bool bounded_key = true;
01533 IDL_GlobalData::DCPS_Data_Type_Info_Iter iter(info->key_list_);
01534 for (ACE_TString* kp = 0; iter.next(kp) != 0; iter.advance()) {
01535 string key_name = ACE_TEXT_ALWAYS_CHAR(kp->c_str());
01536 AST_Type* field_type = 0;
01537 try {
01538 field_type = find_type(fields, key_name);
01539 } catch (const string& error) {
01540 std::cerr << "ERROR: Invalid key specification for " << cxx
01541 << " (" << key_name << "). " << error << std::endl;
01542 return false;
01543 }
01544 if (!is_bounded_type(field_type)) {
01545 bounded_key = false;
01546 break;
01547 }
01548 }
01549
01550 {
01551 Function max_marsh("gen_max_marshaled_size", "size_t");
01552 max_marsh.addArg("stru", "KeyOnly<const " + cxx + ">");
01553 max_marsh.addArg("align", "bool");
01554 max_marsh.endArgs();
01555
01556 if (bounded_key) {
01557 IDL_GlobalData::DCPS_Data_Type_Info_Iter iter(info->key_list_);
01558 size_t size = 0, padding = 0;
01559 for (ACE_TString* kp = 0; iter.next(kp) != 0; iter.advance()) {
01560 string key_name = ACE_TEXT_ALWAYS_CHAR(kp->c_str());
01561 AST_Type* field_type = 0;
01562 try {
01563 field_type = find_type(fields, key_name);
01564 } catch (const string& error) {
01565 std::cerr << "ERROR: Invalid key specification for " << cxx
01566 << " (" << key_name << "). " << error << std::endl;
01567 return false;
01568 }
01569 max_marshaled_size(field_type, size, padding);
01570 }
01571 if (padding) {
01572 be_global->impl_
01573 << " return align ? " << size + padding << " : " << size << ";\n";
01574 } else {
01575 be_global->impl_
01576 << " return " << size << ";\n";
01577 }
01578 } else {
01579 be_global->impl_
01580 << " return 0;\n";
01581 }
01582 }
01583
01584 {
01585 Function find_size("gen_find_size", "void");
01586 find_size.addArg("stru", "KeyOnly<const " + cxx + ">");
01587 find_size.addArg("size", "size_t&");
01588 find_size.addArg("padding", "size_t&");
01589 find_size.endArgs();
01590 string expr, intro;
01591 IDL_GlobalData::DCPS_Data_Type_Info_Iter iter(info->key_list_);
01592 for (ACE_TString* kp = 0; iter.next(kp) != 0; iter.advance()) {
01593 string key_name = ACE_TEXT_ALWAYS_CHAR(kp->c_str());
01594 AST_Type* field_type = 0;
01595 try {
01596 field_type = find_type(fields, key_name);
01597 } catch (const string& error) {
01598 std::cerr << "ERROR: Invalid key specification for " << cxx
01599 << " (" << key_name << "). " << error << std::endl;
01600 return false;
01601 }
01602 expr += findSizeCommon(key_name, field_type, "stru.t", intro);
01603 }
01604 be_global->impl_ << intro << expr;
01605 }
01606
01607 {
01608 Function insertion("operator<<", "bool");
01609 insertion.addArg("strm", "Serializer&");
01610 insertion.addArg("stru", "KeyOnly<const " + cxx + ">");
01611 insertion.endArgs();
01612
01613 bool first = true;
01614 string expr, intro;
01615 IDL_GlobalData::DCPS_Data_Type_Info_Iter iter(info->key_list_);
01616 for (ACE_TString* kp = 0; iter.next(kp) != 0; iter.advance()) {
01617 string key_name = ACE_TEXT_ALWAYS_CHAR(kp->c_str());
01618 AST_Type* field_type = 0;
01619 try {
01620 field_type = find_type(fields, key_name);
01621 } catch (const string& error) {
01622 std::cerr << "ERROR: Invalid key specification for " << cxx
01623 << " (" << key_name << "). " << error << std::endl;
01624 return false;
01625 }
01626 if (first) first = false;
01627 else expr += "\n && ";
01628 expr += streamCommon(key_name, field_type, "<< stru.t", intro);
01629 }
01630 if (first) be_global->impl_ << intro << " return true;\n";
01631 else be_global->impl_ << intro << " return " << expr << ";\n";
01632 }
01633
01634 {
01635 Function extraction("operator>>", "bool");
01636 extraction.addArg("strm", "Serializer&");
01637 extraction.addArg("stru", "KeyOnly<" + cxx + ">");
01638 extraction.endArgs();
01639
01640 bool first = true;
01641 string expr, intro;
01642 IDL_GlobalData::DCPS_Data_Type_Info_Iter iter(info->key_list_);
01643 for (ACE_TString* kp = 0; iter.next(kp) != 0; iter.advance()) {
01644 string key_name = ACE_TEXT_ALWAYS_CHAR(kp->c_str());
01645 AST_Type* field_type = 0;
01646 try {
01647 field_type = find_type(fields, key_name);
01648 } catch (const string& error) {
01649 std::cerr << "ERROR: Invalid key specification for " << cxx
01650 << " (" << key_name << "). " << error << std::endl;
01651 return false;
01652 }
01653 if (first) first = false;
01654 else expr += "\n && ";
01655 expr += streamCommon(key_name, field_type, ">> stru.t", intro);
01656 }
01657 if (first) be_global->impl_ << intro << " return true;\n";
01658 else be_global->impl_ << intro << " return " << expr << ";\n";
01659 }
01660
01661 be_global->header_ <<
01662 "template <>\n"
01663 "struct MarshalTraits<" << cxx << "> {\n"
01664 " static bool gen_is_bounded_size() { return " << (is_bounded_struct ? "true" : "false") << "; }\n"
01665 " static bool gen_is_bounded_key_size() { return " << (bounded_key ? "true" : "false") << "; }\n"
01666 "};\n";
01667 }
01668
01669 return true;
01670 }
01671
01672 namespace {
01673
01674 bool isRtpsSpecialUnion(const string& cxx)
01675 {
01676 return cxx == "OpenDDS::RTPS::Parameter"
01677 || cxx == "OpenDDS::RTPS::Submessage";
01678 }
01679
01680 bool genRtpsParameter(AST_Type* discriminator,
01681 const std::vector<AST_UnionBranch*>& branches)
01682 {
01683 const string cxx = "OpenDDS::RTPS::Parameter";
01684 {
01685 Function find_size("gen_find_size", "void");
01686 find_size.addArg("uni", "const " + cxx + "&");
01687 find_size.addArg("size", "size_t&");
01688 find_size.addArg("padding", "size_t&");
01689 find_size.endArgs();
01690 generateSwitchForUnion("uni._d()", findSizeCommon, branches,
01691 discriminator, "", "", cxx.c_str());
01692 be_global->impl_ <<
01693 " size += 4; // parameterId & length\n";
01694 }
01695 {
01696 Function insertion("operator<<", "bool");
01697 insertion.addArg("outer_strm", "Serializer&");
01698 insertion.addArg("uni", "const " + cxx + "&");
01699 insertion.endArgs();
01700 be_global->impl_ <<
01701 " if (!(outer_strm << uni._d())) {\n"
01702 " return false;\n"
01703 " }\n"
01704 " size_t size = 0, pad = 0;\n"
01705 " gen_find_size(uni, size, pad);\n"
01706 " size -= 4; // parameterId & length\n"
01707 " const size_t post_pad = 4 - ((size + pad) % 4);\n"
01708 " const size_t total = size + pad + ((post_pad < 4) ? post_pad : 0);\n"
01709 " if (size + pad > ACE_UINT16_MAX || "
01710 "!(outer_strm << ACE_CDR::UShort(total))) {\n"
01711 " return false;\n"
01712 " }\n"
01713 " ACE_Message_Block param(size + pad);\n"
01714 " Serializer strm(¶m, outer_strm.swap_bytes(), "
01715 "outer_strm.alignment());\n"
01716 " if (!insertParamData(strm, uni)) {\n"
01717 " return false;\n"
01718 " }\n"
01719 " const ACE_CDR::Octet* data = reinterpret_cast<ACE_CDR::Octet*>("
01720 "param.rd_ptr());\n"
01721 " if (!outer_strm.write_octet_array(data, ACE_CDR::ULong(param.length()))) {\n"
01722 " return false;\n"
01723 " }\n"
01724 " if (post_pad < 4 && outer_strm.alignment() != "
01725 "Serializer::ALIGN_NONE) {\n"
01726 " static const ACE_CDR::Octet padding[3] = {0};\n"
01727 " return outer_strm.write_octet_array(padding, "
01728 "ACE_CDR::ULong(post_pad));\n"
01729 " }\n"
01730 " return true;\n";
01731 }
01732 {
01733 Function insertData("insertParamData", "bool");
01734 insertData.addArg("strm", "Serializer&");
01735 insertData.addArg("uni", "const " + cxx + "&");
01736 insertData.endArgs();
01737 generateSwitchForUnion("uni._d()", streamCommon, branches, discriminator,
01738 "return", "<< ", cxx.c_str());
01739 }
01740 {
01741 Function extraction("operator>>", "bool");
01742 extraction.addArg("outer_strm", "Serializer&");
01743 extraction.addArg("uni", cxx + "&");
01744 extraction.endArgs();
01745 be_global->impl_ <<
01746 " ACE_CDR::UShort disc, size;\n"
01747 " if (!(outer_strm >> disc) || !(outer_strm >> size)) {\n"
01748 " return false;\n"
01749 " }\n"
01750 " if (disc == OpenDDS::RTPS::PID_SENTINEL) {\n"
01751 " uni._d(OpenDDS::RTPS::PID_SENTINEL);\n"
01752 " return true;\n"
01753 " }\n"
01754 " ACE_Message_Block param(size);\n"
01755 " ACE_CDR::Octet* data = reinterpret_cast<ACE_CDR::Octet*>("
01756 "param.wr_ptr());\n"
01757 " if (!outer_strm.read_octet_array(data, size)) {\n"
01758 " return false;\n"
01759 " }\n"
01760 " param.wr_ptr(size);\n"
01761 " Serializer strm(¶m, outer_strm.swap_bytes(), "
01762 "Serializer::ALIGN_CDR);\n"
01763 " switch (disc) {\n";
01764 generateSwitchBody(streamCommon, branches, discriminator,
01765 "return", ">> ", cxx.c_str(), true);
01766 be_global->impl_ <<
01767 " default:\n"
01768 " {\n"
01769 " uni.unknown_data(DDS::OctetSeq(size));\n"
01770 " uni.unknown_data().length(size);\n"
01771 " std::memcpy(uni.unknown_data().get_buffer(), data, size);\n"
01772 " uni._d(disc);\n"
01773 " }\n"
01774 " }\n"
01775 " return true;\n";
01776 }
01777 return true;
01778 }
01779
01780 bool genRtpsSubmessage(AST_Type* discriminator,
01781 const std::vector<AST_UnionBranch*>& branches)
01782 {
01783 const string cxx = "OpenDDS::RTPS::Submessage";
01784 {
01785 Function find_size("gen_find_size", "void");
01786 find_size.addArg("uni", "const " + cxx + "&");
01787 find_size.addArg("size", "size_t&");
01788 find_size.addArg("padding", "size_t&");
01789 find_size.endArgs();
01790 generateSwitchForUnion("uni._d()", findSizeCommon, branches,
01791 discriminator, "", "", cxx.c_str());
01792 }
01793 {
01794 Function insertion("operator<<", "bool");
01795 insertion.addArg("strm", "Serializer&");
01796 insertion.addArg("uni", "const " + cxx + "&");
01797 insertion.endArgs();
01798 generateSwitchForUnion("uni._d()", streamCommon, branches,
01799 discriminator, "return", "<< ", cxx.c_str());
01800 }
01801 {
01802 Function insertion("operator>>", "bool");
01803 insertion.addArg("strm", "Serializer&");
01804 insertion.addArg("uni", cxx + "&");
01805 insertion.endArgs();
01806 be_global->impl_ << " // unused\n return false;\n";
01807 }
01808 return true;
01809 }
01810
01811 bool genRtpsSpecialUnion(const string& cxx, AST_Type* discriminator,
01812 const std::vector<AST_UnionBranch*>& branches)
01813 {
01814 if (cxx == "OpenDDS::RTPS::Parameter") {
01815 return genRtpsParameter(discriminator, branches);
01816 } else if (cxx == "OpenDDS::RTPS::Submessage") {
01817 return genRtpsSubmessage(discriminator, branches);
01818 } else {
01819 return false;
01820 }
01821 }
01822 }
01823
01824 bool marshal_generator::gen_union(AST_Union*, UTL_ScopedName* name,
01825 const std::vector<AST_UnionBranch*>& branches, AST_Type* discriminator,
01826 const char*)
01827 {
01828 NamespaceGuard ng;
01829 be_global->add_include("dds/DCPS/Serializer.h");
01830 string cxx = scoped(name);
01831
01832 for (size_t i = 0; i < LENGTH(special_unions); ++i) {
01833 if (special_unions[i].check(cxx)) {
01834 return special_unions[i].gen(cxx, discriminator, branches);
01835 }
01836 }
01837
01838 const string wrap_out = getWrapper("uni._d()", discriminator, WD_OUTPUT);
01839 {
01840 Function find_size("gen_find_size", "void");
01841 find_size.addArg("uni", "const " + cxx + "&");
01842 find_size.addArg("size", "size_t&");
01843 find_size.addArg("padding", "size_t&");
01844 find_size.endArgs();
01845 const string align = getAlignment(discriminator);
01846 if (!align.empty()) {
01847 be_global->impl_ <<
01848 " if ((size + padding) % " << align << ") {\n"
01849 " padding += " << align << " - ((size + padding) % " << align
01850 << ");\n"
01851 " }\n";
01852 }
01853 be_global->impl_ <<
01854 " size += gen_max_marshaled_size(" << wrap_out << ");\n";
01855 generateSwitchForUnion("uni._d()", findSizeCommon, branches, discriminator,
01856 "", "", cxx.c_str());
01857 }
01858 {
01859 Function insertion("operator<<", "bool");
01860 insertion.addArg("strm", "Serializer&");
01861 insertion.addArg("uni", "const " + cxx + "&");
01862 insertion.endArgs();
01863 be_global->impl_ <<
01864 streamAndCheck("<< " + wrap_out);
01865 if (generateSwitchForUnion("uni._d()", streamCommon, branches,
01866 discriminator, "return", "<< ", cxx.c_str())) {
01867 be_global->impl_ <<
01868 " return true;\n";
01869 }
01870 }
01871 {
01872 Function extraction("operator>>", "bool");
01873 extraction.addArg("strm", "Serializer&");
01874 extraction.addArg("uni", cxx + "&");
01875 extraction.endArgs();
01876 be_global->impl_ <<
01877 " " << scoped(discriminator->name()) << " disc;\n" <<
01878 streamAndCheck(">> " + getWrapper("disc", discriminator, WD_INPUT));
01879 if (generateSwitchForUnion("disc", streamCommon, branches,
01880 discriminator, "if", ">> ", cxx.c_str())) {
01881 be_global->impl_ <<
01882 " return true;\n";
01883 }
01884 }
01885 return true;
01886 }