OpenDDS  Snapshot(2023/04/28-20:55)
metaclass_generator.cpp
Go to the documentation of this file.
1 /*
2  * Distributed under the OpenDDS License.
3  * See: http://www.opendds.org/license.html
4  */
5 
6 #include "metaclass_generator.h"
7 
8 #include "marshal_generator.h"
9 #include "field_info.h"
10 #include "be_extern.h"
11 #include "topic_keys.h"
12 
13 #include <utl_identifier.h>
14 
15 #include <cstddef>
16 #include <stdexcept>
17 
18 using namespace AstTypeClassification;
19 
20 namespace {
21  class ContentSubscriptionGuard : public PreprocessorIfGuard {
22  public:
23  ContentSubscriptionGuard()
24  : PreprocessorIfGuard("ndef OPENDDS_NO_CONTENT_SUBSCRIPTION_PROFILE")
25  {
26  }
27  };
28 }
29 
30 bool
31 metaclass_generator::gen_enum(AST_Enum*, UTL_ScopedName* name,
32  const std::vector<AST_EnumVal*>& contents, const char*)
33 {
34  NamespaceGuard ng;
35  std::string array_decl = "const char* gen_" + scoped_helper(name, "_") + "_names[]";
36  std::string size_decl = "const size_t gen_" + scoped_helper(name, "_") + "_names_size";
37  std::string decl_prefix = ((be_global->export_macro() == "") ? std::string("extern ") : (std::string(be_global->export_macro().c_str()) + " extern "));
38  be_global->header_ << decl_prefix << array_decl << ";\n";
39  be_global->header_ << decl_prefix << size_decl << ";\n";
40  be_global->impl_ << array_decl << " = {\n";
41  for (size_t i = 0; i < contents.size(); ++i) {
42  be_global->impl_ << " \"" << canonical_name(contents[i])
43  << ((i < contents.size() - 1) ? "\",\n" : "\"\n");
44  }
45  be_global->impl_ << "};\n";
46  be_global->impl_ << size_decl << " = " << contents.size() << ";\n";
47  return true;
48 }
49 
50 namespace {
51 
52  void
53  delegateToNested(const std::string& fieldName, AST_Field* field,
54  const std::string& firstArg)
55  {
56  const size_t n = fieldName.size() + 1 /* 1 for the dot */;
57  const std::string fieldType = scoped(field->field_type()->name());
58  be_global->impl_ <<
59  " if (std::strncmp(field, \"" << fieldName << ".\", " << n
60  << ") == 0) {\n"
61  " return getMetaStruct<" << fieldType << ">().getValue("
62  << firstArg << ", field + " << n << ");\n"
63  " }\n";
64  }
65 
66  void
67  gen_field_getValue(AST_Field* field)
68  {
69  const bool use_cxx11 = be_global->language_mapping() == BE_GlobalData::LANGMAP_CXX11;
70  const Classification cls = classify(field->field_type());
71  const std::string fieldName = field->local_name()->get_string();
72  const std::string idl_name = canonical_name(field);
73  if (cls & CL_SCALAR) {
74  std::string prefix, suffix;
75  if (cls & CL_ENUM) {
76  AST_Type* enum_type = resolveActualType(field->field_type());
77  prefix = "gen_" +
78  dds_generator::scoped_helper(enum_type->name(), "_")
79  + "_names[";
80  if (use_cxx11) {
81  prefix += "static_cast<int>(";
82  }
83  suffix = use_cxx11 ? "())]" : "]";
84  } else if (use_cxx11) {
85  suffix += "()";
86  }
87  const std::string string_to_ptr = use_cxx11 ? "" : ".in()";
88  be_global->impl_ <<
89  " if (std::strcmp(field, \"" << idl_name << "\") == 0) {\n"
90  " return " + prefix + "typed." + fieldName
91  + (cls & CL_STRING ? string_to_ptr : "") + suffix + ";\n"
92  " }\n";
93  be_global->add_include("<cstring>", BE_GlobalData::STREAM_CPP);
94  } else if (cls & CL_STRUCTURE) {
95  delegateToNested(idl_name, field,
96  "&typed." + std::string(use_cxx11 ? "_" : "") + fieldName);
97  be_global->add_include("<cstring>", BE_GlobalData::STREAM_CPP);
98  }
99  }
100 
101  void
102  gen_field_createQC(AST_Field* field)
103  {
104  const bool use_cxx11 = be_global->language_mapping() == BE_GlobalData::LANGMAP_CXX11;
105  Classification cls = classify(field->field_type());
106  const std::string fieldName = field->local_name()->get_string();
107  const std::string idl_name = canonical_name(field);
108  if (cls & CL_SCALAR) {
109  be_global->impl_ <<
110  " if (std::strcmp(field, \"" << idl_name << "\") == 0) {\n"
111  " return make_field_cmp(&T::" << (use_cxx11 ? "_" : "")
112  << fieldName << ", next);\n"
113  " }\n";
114  be_global->add_include("<cstring>", BE_GlobalData::STREAM_CPP);
115  } else if (cls & CL_STRUCTURE) {
116  const size_t n = idl_name.size() + 1 /* 1 for the dot */;
117  std::string fieldType = scoped(field->field_type()->name());
118  be_global->impl_ <<
119  " if (std::strncmp(field, \"" << idl_name << ".\", " << n <<
120  ") == 0) {\n"
121  " return make_struct_cmp(&T::" << (use_cxx11 ? "_" : "")
122  << fieldName <<
123  ", getMetaStruct<" << fieldType << ">().create_qc_comparator("
124  "field + " << n << "), next);\n"
125  " }\n";
126  }
127  }
128 
129  void
130  print_field_name(AST_Field* field)
131  {
132  be_global->impl_ << '"' << canonical_name(field) << '"' << ", ";
133  }
134 
135  void
136  get_raw_field(AST_Field* field)
137  {
138  const bool use_cxx11 = be_global->language_mapping() == BE_GlobalData::LANGMAP_CXX11;
139  const char* fieldName = field->local_name()->get_string();
140  const std::string idl_name = canonical_name(field);
141  be_global->impl_ <<
142  " if (std::strcmp(field, \"" << idl_name << "\") == 0) {\n"
143  " return &static_cast<const T*>(stru)->" << (use_cxx11 ? "_" : "")
144  << fieldName << ";\n"
145  " }\n";
146  be_global->add_include("<cstring>", BE_GlobalData::STREAM_CPP);
147  }
148 
149  void
150  assign_field(AST_Field* field)
151  {
152  const bool use_cxx11 = be_global->language_mapping() == BE_GlobalData::LANGMAP_CXX11;
153  Classification cls = classify(field->field_type());
154  if (!cls) return; // skip CL_UNKNOWN types
155  std::string fieldType = (cls & CL_STRING) ?
156  string_type(cls) : scoped(field->field_type()->name());
157  FieldInfo af(*field);
158  if (af.as_base_ && af.type_->anonymous()) {
159  fieldType = af.scoped_type_;
160  }
161  const std::string idl_name = canonical_name(field);
162  if ((cls & (CL_SCALAR | CL_STRUCTURE | CL_SEQUENCE | CL_UNION))
163  || (use_cxx11 && (cls & CL_ARRAY))) {
164  be_global->impl_ <<
165  " if (std::strcmp(field, \"" << idl_name << "\") == 0) {\n"
166  " static_cast<T*>(lhs)->" << (use_cxx11 ? "_" : "") << af.name_ <<
167  " = *static_cast<const " << fieldType <<
168  "*>(rhsMeta.getRawField(rhs, rhsFieldSpec));\n"
169  " return;\n"
170  " }\n";
171  be_global->add_include("<cstring>", BE_GlobalData::STREAM_CPP);
172  } else if (cls & CL_ARRAY) {
173  AST_Type* unTD = resolveActualType(field->field_type());
174  AST_Array* arr = dynamic_cast<AST_Array*>(unTD);
175  be_global->impl_ <<
176  " if (std::strcmp(field, \"" << idl_name << "\") == 0) {\n"
177  " " << fieldType << "* lhsArr = &static_cast<T*>(lhs)->" << af.name_ << ";\n"
178  " const " << fieldType << "* rhsArr = static_cast<const " <<
179  fieldType << "*>(rhsMeta.getRawField(rhs, rhsFieldSpec));\n";
180  be_global->add_include("<cstring>", BE_GlobalData::STREAM_CPP);
181  AST_Type* elem = arr->base_type();
182  AST_Type* elemUnTD = resolveActualType(elem);
183  if (classify(elemUnTD) & CL_ARRAY) {
184  // array-of-array case, fall back on the Serializer
185  be_global->impl_ <<
186  " " << fieldType << "_forany rhsForany(const_cast<" <<
187  fieldType << "_slice*>(*rhsArr));\n"
188  // TODO(iguessthislldo) I'm not 100% certain this will always work
189  " const Encoding encoding(Encoding::KIND_UNALIGNED_CDR);\n"
190  " ACE_Message_Block mb(serialized_size(encoding, rhsForany));\n"
191  " Serializer ser_out(&mb, encoding);\n"
192  " ser_out << rhsForany;\n"
193  " " << fieldType << "_forany lhsForany(*lhsArr);\n"
194  " Serializer ser_in(&mb, encoding);\n"
195  " ser_in >> lhsForany;\n";
196  } else {
197  std::string indent = " ";
198  NestedForLoops nfl("CORBA::ULong", "i", arr, indent);
199  be_global->impl_ <<
200  indent << "(*lhsArr)" << nfl.index_ << " = (*rhsArr)" <<
201  nfl.index_ << ";\n";
202  }
203  be_global->impl_ <<
204  " return;\n"
205  " }\n";
206  }
207  }
208 
209  void
210  compare_field(AST_Field* field)
211  {
212  const bool use_cxx11 = be_global->language_mapping() == BE_GlobalData::LANGMAP_CXX11;
213  Classification cls = classify(field->field_type());
214  if (!(cls & CL_SCALAR)) return;
215  const char* fieldName = field->local_name()->get_string();
216  const std::string idl_name = canonical_name(field);
217  be_global->impl_ <<
218  " if (std::strcmp(field, \"" << idl_name << "\") == 0) {\n";
219  be_global->add_include("<cstring>", BE_GlobalData::STREAM_CPP);
220  if (!use_cxx11 && (cls & CL_STRING)) {
221  be_global->impl_ << // ACE_OS::strcmp has overloads for narrow & wide
222  " return 0 == ACE_OS::strcmp(static_cast<const T*>(lhs)->"
223  << fieldName << ".in(), static_cast<const T*>(rhs)->" << fieldName
224  << ".in());\n";
225  } else {
226  be_global->impl_ <<
227  " return static_cast<const T*>(lhs)->" << (use_cxx11 ? "_" : "")
228  << fieldName << " == static_cast<const T*>(rhs)->" << (use_cxx11 ? "_" : "")
229  << fieldName << ";\n";
230  }
231  be_global->impl_ << " }\n";
232  }
233 
234  bool
235  generate_metaclass(AST_Decl* node, UTL_ScopedName* name,
236  const std::vector<AST_Field*>& fields, bool& first_struct_,
237  const std::string& clazz)
238  {
239  AST_Structure* struct_node = 0;
240  AST_Union* union_node = 0;
241  if (!node || !name) {
242  return false;
243  }
244  if (node->node_type() == AST_Decl::NT_struct) {
245  struct_node = dynamic_cast<AST_Structure*>(node);
246  } else if (node->node_type() == AST_Decl::NT_union) {
247  union_node = dynamic_cast<AST_Union*>(node);
248  } else {
249  return false;
250  }
251  const std::string type_idl_name = canonical_name(name);
252 
253  if (first_struct_) {
254  be_global->header_ <<
255  "class MetaStruct;\n\n"
256  "template<typename T>\n"
257  "const MetaStruct& getMetaStruct();\n\n";
258  first_struct_ = false;
259  }
260 
261  be_global->add_include("dds/DCPS/FilterEvaluator.h",
262  BE_GlobalData::STREAM_CPP);
263 
264  std::string decl = "const MetaStruct& getMetaStruct<" + clazz + ">()",
265  exp = be_global->export_macro().c_str();
266  be_global->header_ << "template<>\n" << exp << (exp.length() ? "\n" : "")
267  << decl << ";\n";
268 
269  size_t key_count = 0;
270  IDL_GlobalData::DCPS_Data_Type_Info* info = 0;
271  const bool is_topic_type = be_global->is_topic_type(node);
272  if (struct_node) {
273  info = idl_global->is_dcps_type(name);
274  if (is_topic_type) {
275  key_count = TopicKeys(struct_node).count();
276  } else if (info) {
277  key_count = info->key_list_.size();
278  }
279  } else { // Union
280  key_count = be_global->union_discriminator_is_key(union_node) ? 1 : 0;
281  }
282 
283  const std::string exception =
284  "throw std::runtime_error(\"Field \" + OPENDDS_STRING(field) + \" not "
285  "found or its type is not supported (in struct" + clazz + ")\");\n";
286 
287  be_global->impl_ <<
288  "template<>\n"
289  "struct MetaStructImpl<" << clazz << "> : MetaStruct {\n"
290  " typedef " << clazz << " T;\n\n"
291  "#ifndef OPENDDS_NO_MULTI_TOPIC\n"
292  " void* allocate() const { return new T; }\n\n"
293  " void deallocate(void* stru) const { delete static_cast<T*>(stru); }\n\n"
294  " size_t numDcpsKeys() const { return " << key_count << "; }\n\n"
295  "#endif /* OPENDDS_NO_MULTI_TOPIC */\n\n";
296  if (struct_node && be_global->extensibility(struct_node) == extensibilitykind_mutable) {
297  be_global->impl_ <<
298  " ACE_CDR::ULong map_name_to_id(const char* field) const\n"
299  " {\n"
300  " static const std::pair<std::string, ACE_CDR::ULong> name_to_id_pairs[] = {\n";
301  for (size_t i = 0; i < fields.size(); ++i) {
302  be_global->impl_ << " std::make_pair(\"" << canonical_name(fields[i]) << "\", " <<
303  be_global->get_id(fields[i]) << "),\n";
304  }
305  be_global->impl_ <<
306  " };\n"
307  " static const std::map<std::string, ACE_CDR::ULong> name_to_id_map(name_to_id_pairs,"
308  " name_to_id_pairs + " << fields.size() << ");\n"
309  " std::map<std::string, ACE_CDR::ULong>::const_iterator it = name_to_id_map.find(field);\n"
310  " if (it == name_to_id_map.end()) {\n"
311  " " << exception <<
312  " } else {\n"
313  " return it->second;\n"
314  " }\n"
315  " }\n\n";
316  }
317  be_global->impl_ <<
318  " Value getValue(const void* stru, const char* field) const\n"
319  " {\n"
320  " const" << clazz << "& typed = *static_cast<const" << clazz << "*>(stru);\n"
321  " ACE_UNUSED_ARG(typed);\n";
322  std::for_each(fields.begin(), fields.end(), gen_field_getValue);
323  be_global->impl_ <<
324  " " << exception <<
325  " }\n\n";
326  if (struct_node) {
328  } else {
329  be_global->impl_ <<
330  " Value getValue(Serializer& ser, const char* field, const TypeSupportImpl* = 0) const\n"
331  " {\n"
332  " ACE_UNUSED_ARG(ser);\n"
333  " if (!field[0]) {\n" // if 'field' is the empty string...
334  " return 0;\n" // ...we've skipped the entire struct
335  " }\n" // and the return value is ignored
336  " throw std::runtime_error(\"Field \" + OPENDDS_STRING(field) + \" not "
337  "valid for union" << type_idl_name << "\");\n"
338  " }\n\n";
339  }
340  be_global->impl_ <<
341  " ComparatorBase::Ptr create_qc_comparator(const char* field, "
342  "ComparatorBase::Ptr next) const\n"
343  " {\n"
344  " ACE_UNUSED_ARG(next);\n";
345  be_global->add_include("<stdexcept>", BE_GlobalData::STREAM_CPP);
346  if (struct_node) {
347  std::for_each(fields.begin(), fields.end(), gen_field_createQC);
348  }
349  be_global->impl_ <<
350  " " << exception <<
351  " }\n\n"
352  "#ifndef OPENDDS_NO_MULTI_TOPIC\n"
353  " const char** getFieldNames() const\n"
354  " {\n"
355  " static const char* names[] = {";
356  if (struct_node) {
357  std::for_each(fields.begin(), fields.end(), print_field_name);
358  }
359  be_global->impl_ <<
360  "0};\n"
361  " return names;\n"
362  " }\n\n"
363  " const void* getRawField(const void* stru, const char* field) const\n"
364  " {\n";
365  if (struct_node && fields.size()) {
366  std::for_each(fields.begin(), fields.end(), get_raw_field);
367  } else {
368  be_global->impl_ << " ACE_UNUSED_ARG(stru);\n";
369  }
370  be_global->impl_ <<
371  " " << exception <<
372  " }\n\n"
373  " void assign(void* lhs, const char* field, const void* rhs,\n"
374  " const char* rhsFieldSpec, const MetaStruct& rhsMeta) const\n"
375  " {\n"
376  " ACE_UNUSED_ARG(lhs);\n"
377  " ACE_UNUSED_ARG(field);\n"
378  " ACE_UNUSED_ARG(rhs);\n"
379  " ACE_UNUSED_ARG(rhsFieldSpec);\n"
380  " ACE_UNUSED_ARG(rhsMeta);\n";
381  if (struct_node) {
382  std::for_each(fields.begin(), fields.end(), assign_field);
383  }
384  be_global->impl_ <<
385  " " << exception <<
386  " }\n"
387  "\n"
388  " bool compare(const void* lhs, const void* rhs, const char* field) "
389  "const\n"
390  " {\n"
391  " ACE_UNUSED_ARG(lhs);\n"
392  " ACE_UNUSED_ARG(field);\n"
393  " ACE_UNUSED_ARG(rhs);\n";
394  if (struct_node) {
395  std::for_each(fields.begin(), fields.end(), compare_field);
396  }
397  be_global->impl_ <<
398  " " << exception <<
399  " }\n"
400  "#endif /* OPENDDS_NO_MULTI_TOPIC */\n\n"
401  "};\n\n"
402  "template<>\n"
403  << decl << "\n"
404  "{\n"
405  " static MetaStructImpl<" << clazz << "> msi;\n"
406  " return msi;\n"
407  "}\n\n";
408  return true;
409  }
410 }
411 
412 void generate_anon_fields(AST_Structure* node)
413 {
414  const Fields fields(node);
415  FieldInfo::EleLenSet anonymous_seq_generated;
416  for (Fields::Iterator i = fields.begin(); i != fields.end(); ++i) {
417  AST_Field* const field = *i;
418  if (field->field_type()->anonymous()) {
419  FieldInfo af(*field);
420  if (af.arr_ || (af.seq_ && af.is_new(anonymous_seq_generated))) {
421  Function f("gen_skip_over", "bool");
422  f.addArg("ser", "Serializer&");
423  f.addArg("", af.ptr_);
424  f.endArgs();
425 
426  AST_Type* elem;
427  if (af.seq_ != 0) {
428  elem = af.seq_->base_type();
429  } else {
430  elem = af.arr_->base_type();
431  }
432  be_global->impl_ <<
433  " const Encoding& encoding = ser.encoding();\n"
434  " ACE_UNUSED_ARG(encoding);\n";
435  Classification elem_cls = classify(elem);
436  const bool primitive = elem_cls & CL_PRIMITIVE;
438  " if (!ser.read_delimiter(total_size)) {\n"
439  " return false;\n"
440  " }\n", !primitive, true);
441 
442  std::string len;
443  if (af.arr_) {
444  std::ostringstream strstream;
445  strstream << array_element_count(af.arr_);
446  len = strstream.str();
447  } else { // Sequence
448  be_global->impl_ <<
449  " ACE_CDR::ULong length;\n"
450  " if (!(ser >> length)) return false;\n";
451  len = "length";
452  }
453  const std::string cxx_elem = scoped(elem->name());
454  AST_Type* elem_orig = elem;
455  elem = resolveActualType(elem);
456  elem_cls = classify(elem);
457 
458  if ((elem_cls & (CL_PRIMITIVE | CL_ENUM))) {
459  // fixed-length sequence/array element -> skip all elements at once
460  size_t sz = 0;
461  to_cxx_type(af.as_act_, sz);
462  be_global->impl_ <<
463  " return ser.skip(" << af.length_ << ", " << sz << ");\n";
464  } else {
465  be_global->impl_ <<
466  " for (ACE_CDR::ULong i = 0; i < " << len << "; ++i) {\n";
467  if (elem_cls & CL_STRING) {
468  be_global->impl_ <<
469  " ACE_CDR::ULong strlength;\n"
470  " if (!(ser >> strlength && ser.skip(strlength))) return false;\n";
471  } else if (elem_cls & (CL_ARRAY | CL_SEQUENCE | CL_STRUCTURE)) {
472  std::string pre, post;
473  const bool use_cxx11 = be_global->language_mapping() == BE_GlobalData::LANGMAP_CXX11;
474  if (!use_cxx11 && (elem_cls & CL_ARRAY)) {
475  post = "_forany";
476  } else if (use_cxx11 && (elem_cls & (CL_ARRAY | CL_SEQUENCE))) {
477  pre = "IDL::DistinctType<";
478  post = ", " + dds_generator::get_tag_name(dds_generator::scoped_helper(deepest_named_type(elem_orig)->name(), "_")) + ">";
479  }
480  be_global->impl_ <<
481  " if (!gen_skip_over(ser, static_cast<" << pre << cxx_elem << post
482  << "*>(0))) return false;\n";
483  }
484  be_global->impl_ <<
485  " }\n"
486  " return true;\n";
487  }
488 
489  }
490  }
491  }
492 }
493 
494 bool
495 metaclass_generator::gen_struct(AST_Structure* node, UTL_ScopedName* name,
496  const std::vector<AST_Field*>& fields, AST_Type::SIZE_TYPE, const char*)
497 {
498  const std::string clazz = scoped(name);
499 
500  be_global->add_include("dds/DCPS/PoolAllocator.h",
501  BE_GlobalData::STREAM_CPP);
502 
503  ContentSubscriptionGuard csg;
504  NamespaceGuard ng;
505 
506  if (!generate_metaclass(node, name, fields, first_struct_, clazz)) {
507  return false;
508  }
509 
510  generate_anon_fields(node);
511 
512  {
513  Function f("gen_skip_over", "bool");
514  f.addArg("ser", "Serializer&");
515  f.addArg("", clazz + "*");
516  f.endArgs();
517  be_global->impl_ <<
518  " MetaStructImpl<" << clazz << ">().getValue(ser, \"\");\n"
519  " return true;\n";
520  }
521  return true;
522 }
523 
524 bool
525 metaclass_generator::gen_typedef(AST_Typedef*, UTL_ScopedName* name,
526  AST_Type* type, const char*)
527 {
528  AST_Array* arr = dynamic_cast<AST_Array*>(type);
529  AST_Sequence* seq = 0;
530  if (!arr && !(seq = dynamic_cast<AST_Sequence*>(type))) {
531  return true;
532  }
533  const bool use_cxx11 = be_global->language_mapping() == BE_GlobalData::LANGMAP_CXX11;
534  const std::string clazz = scoped(name);
535 
536  ContentSubscriptionGuard csg;
537  NamespaceGuard ng;
538  Function f("gen_skip_over", "bool");
539  f.addArg("ser", "Serializer&");
540  if (use_cxx11) {
541  f.addArg("", "IDL::DistinctType<" + clazz + ", " + dds_generator::get_tag_name(clazz) +">*");
542  } else {
543  f.addArg("", clazz + (arr ? "_forany*" : "*"));
544  }
545  f.endArgs();
546 
547  AST_Type* elem;
548  if (seq != 0) {
549  elem = seq->base_type();
550  } else {
551  elem = arr->base_type();
552  }
553  be_global->impl_ <<
554  " const Encoding& encoding = ser.encoding();\n"
555  " ACE_UNUSED_ARG(encoding);\n";
556  Classification elem_cls = classify(elem);
557  const bool primitive = elem_cls & CL_PRIMITIVE;
559  " if (!ser.read_delimiter(total_size)) {\n"
560  " return false;\n"
561  " }\n", !primitive, true);
562 
563  std::string len;
564 
565  if (arr) {
566  std::ostringstream strstream;
567  strstream << array_element_count(arr);
568  len = strstream.str();
569  } else { // Sequence
570  be_global->impl_ <<
571  " ACE_CDR::ULong length;\n"
572  " if (!(ser >> length)) return false;\n";
573  len = "length";
574  }
575 
576  const std::string cxx_elem = scoped(elem->name());
577  AST_Type* elem_orig = elem;
578  elem = resolveActualType(elem);
579  elem_cls = classify(elem);
580 
581  if ((elem_cls & (CL_PRIMITIVE | CL_ENUM))) {
582  // fixed-length sequence/array element -> skip all elements at once
583  size_t sz = 0;
584  to_cxx_type(elem, sz);
585  be_global->impl_ <<
586  " return ser.skip(" << len << ", " << sz << ");\n";
587  } else {
588  be_global->impl_ <<
589  " for (ACE_CDR::ULong i = 0; i < " << len << "; ++i) {\n";
590  if (elem_cls & CL_STRING) {
591  be_global->impl_ <<
592  " ACE_CDR::ULong strlength;\n"
593  " if (!(ser >> strlength && ser.skip(strlength))) return false;\n";
594  } else if (elem_cls & (CL_ARRAY | CL_SEQUENCE | CL_STRUCTURE)) {
595  std::string pre, post;
596  if (!use_cxx11 && (elem_cls & CL_ARRAY)) {
597  post = "_forany";
598  } else if (use_cxx11 && (elem_cls & (CL_ARRAY | CL_SEQUENCE))) {
599  pre = "IDL::DistinctType<";
600  post = ", " + dds_generator::get_tag_name(scoped_helper(deepest_named_type(elem_orig)->name(), "::")) + ">";
601  }
602  be_global->impl_ <<
603  " if (!gen_skip_over(ser, static_cast<" << pre << cxx_elem << post
604  << "*>(0))) return false;\n";
605  }
606  be_global->impl_ <<
607  " }\n"
608  " return true;\n";
609  }
610 
611  return true;
612 }
613 
614 static
615 std::string gen_union_branch(const std::string&, AST_Decl* branch, const std::string&,
616  AST_Type* br_type, const std::string&, bool, Intro&, const std::string&)
617 {
618  const bool use_cxx11 = be_global->language_mapping() == BE_GlobalData::LANGMAP_CXX11;
619  std::stringstream ss;
620  const Classification br_cls = classify(br_type);
621  ss <<
622  " if (is_mutable && !ser.read_parameter_id(member_id, field_size, must_understand)) {\n"
623  " return false;\n"
624  " }\n";
625  if (br_cls & CL_STRING) {
626  ss <<
627  " ACE_CDR::ULong len;\n"
628  " if (!(ser >> len && ser.skip(len))) return false;\n";
629  } else if (br_cls & CL_SCALAR) {
630  size_t sz = 0;
631  to_cxx_type(br_type, sz);
632  ss <<
633  " if (!ser.skip(1, " << sz << ")) return false;\n";
634  } else {
635  std::string pre, post;
636  if (!use_cxx11 && (br_cls & CL_ARRAY)) {
637  post = "_forany";
638  } else if (use_cxx11 && (br_cls & (CL_ARRAY | CL_SEQUENCE))) {
639  pre = "IDL::DistinctType<";
641  }
642  ss <<
643  " if (!gen_skip_over(ser, static_cast<" << pre
644  << field_type_name(dynamic_cast<AST_Field*>(branch), br_type) << post <<
645  "*>(0))) return false;\n";
646  }
647 
648  ss <<
649  " return true;\n";
650  return ss.str();
651 }
652 
653 bool
654 metaclass_generator::gen_union(AST_Union* node, UTL_ScopedName* name,
655  const std::vector<AST_UnionBranch*>& branches, AST_Type* discriminator,
656  const char*)
657 {
658  const std::string clazz = scoped(name);
659 
660  ContentSubscriptionGuard csg;
661  NamespaceGuard ng;
662 
663  std::vector<AST_Field*> dummy_field_list;
664  if (!generate_metaclass(node, name, dummy_field_list, first_struct_, clazz)) {
665  return false;
666  }
667 
668  generate_anon_fields(node);
669 
670  {
671  Function f("gen_skip_over", "bool");
672  f.addArg("ser", "Serializer&");
673  f.addArg("", clazz + "*");
674  f.endArgs();
675 
676  const ExtensibilityKind exten = be_global->extensibility(node);
677  const bool not_final = exten != extensibilitykind_final;
678  const bool is_mutable = exten == extensibilitykind_mutable;
679  be_global->impl_ <<
680  " const Encoding& encoding = ser.encoding();\n"
681  " ACE_UNUSED_ARG(encoding);\n"
682  " const bool is_mutable = " << is_mutable <<";\n"
683  " unsigned member_id;\n"
684  " size_t field_size;\n"
685  " bool must_understand = false;\n";
687  " if (!ser.read_delimiter(total_size)) {\n"
688  " return false;\n"
689  " }\n", not_final);
690  if (is_mutable) {
691  be_global->impl_ <<
692  " if (!ser.read_parameter_id(member_id, field_size, must_understand)) {\n"
693  " return false;\n"
694  " }\n";
695  }
696  be_global->impl_ <<
697  " " << scoped(discriminator->name()) << " disc;\n"
698  " if (!(ser >> " << getWrapper("disc", discriminator, WD_INPUT) << ")) {\n"
699  " return false;\n"
700  " }\n";
701  if (generateSwitchForUnion(node, "disc", gen_union_branch, branches, discriminator, "", "", "",
702  false, true, false)) {
703  be_global->impl_ <<
704  " return true;\n";
705  }
706  }
707  return true;
708 }
std::string to_cxx_type(AST_Type *type, std::size_t &size)
bool is_new(EleLenSet &el_set) const
Definition: field_info.cpp:132
Classification classify(AST_Type *type)
static std::string scoped_helper(UTL_ScopedName *sn, const char *sep, EscapeContext cxt=EscapeContext_Normal)
const char * c_str(void) const
bool gen_union(AST_Union *node, UTL_ScopedName *name, const std::vector< AST_UnionBranch *> &branches, AST_Type *type, const char *repoid)
std::string length_
Definition: field_info.h:59
std::string string_type(AstTypeClassification::Classification cls)
const Classification CL_STRING
static void gen_field_getValueFromSerialized(AST_Structure *node, const std::string &clazz)
Iterator begin() const
const Classification CL_SCALAR
std::string field_type_name(AST_Field *field, AST_Type *field_type)
const Classification CL_PRIMITIVE
bool gen_enum(AST_Enum *node, UTL_ScopedName *name, const std::vector< AST_EnumVal *> &contents, const char *repoid)
static std::string get_tag_name(const std::string &base_name, const std::string &qualifier="")
ExtensibilityKind
Definition: annotations.h:278
AST_Type * deepest_named_type(AST_Type *type)
const Classification CL_ARRAY
std::string ptr_
Definition: field_info.h:66
AST_Type * as_act_
Definition: field_info.h:51
static std::string gen_union_branch(const std::string &, AST_Decl *branch, const std::string &, AST_Type *br_type, const std::string &, bool, Intro &, const std::string &)
bool generateSwitchForUnion(AST_Union *u, const char *switchExpr, CommonFn commonFn, const std::vector< AST_UnionBranch *> &branches, AST_Type *discriminator, const char *statementPrefix, const char *namePrefix="", const char *uni="", bool forceDisableDefault=false, bool parens=true, bool breaks=true, CommonFn commonFn2=0)
returns true if a default: branch was generated (no default: label in IDL)
std::string canonical_name(UTL_ScopedName *sn)
std::string index_
Iterator end() const
size_t count()
Definition: topic_keys.cpp:515
std::string getWrapper(const std::string &name, AST_Type *type, WrapDirection wd)
AST_Type * resolveActualType(AST_Type *element)
void endArgs()
static void generate_dheader_code(const std::string &code, bool dheader_required, bool is_ser_func=true)
const char *const name
Definition: debug.cpp:60
std::string scoped(UTL_ScopedName *sn, EscapeContext ec=EscapeContext_Normal)
AST_Array * arr_
Definition: field_info.h:48
bool gen_typedef(AST_Typedef *node, UTL_ScopedName *name, AST_Type *type, const char *repoid)
std::set< EleLen > EleLenSet
Definition: field_info.h:31
const Classification CL_STRUCTURE
void addArg(const char *name, const std::string &type)
BE_GlobalData * be_global
Definition: be_global.cpp:44
ACE_CDR::ULong array_element_count(AST_Array *arr)
bool gen_struct(AST_Structure *node, UTL_ScopedName *name, const std::vector< AST_Field *> &fields, AST_Type::SIZE_TYPE size, const char *repoid)
const Classification CL_ENUM
const Classification CL_SEQUENCE
DDS::ReturnCode_t key_count(DDS::DynamicType_ptr type, size_t &count)
void generate_anon_fields(AST_Structure *node)
AST_Sequence * seq_
Definition: field_info.h:49
const Classification CL_UNION