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