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