OpenDDS  Snapshot(2023/04/28-20:55)
dds_generator.h
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 #ifndef dds_generator_H
7 #define dds_generator_H
8 
9 #include "be_extern.h"
10 #include "be_util.h"
11 
12 #include <dds/DCPS/ValueHelper.h>
13 
14 #include <utl_scoped_name.h>
15 #include <utl_identifier.h>
16 #include <utl_string.h>
17 #include <ast.h>
18 #include <ast_component_fwd.h>
19 #include <ast_eventtype_fwd.h>
20 #include <ast_structure_fwd.h>
21 #include <ast_union_fwd.h>
22 #include <ast_valuetype_fwd.h>
23 
24 #include <ace/CDR_Base.h>
25 
26 #include <string>
27 #include <vector>
28 #include <cstring>
29 #include <set>
30 #include <stdexcept>
31 #include <iomanip>
32 #include <cctype>
33 #include <climits>
34 
35 /// How to handle IDL underscore escaping. Depends on where the name is
36 /// going and where the name came from.
38  /// This is for generated IDL. (Like *TypeSupport.idl)
40  /// This is for a name coming from generated IDL. (Like *TypeSupportC.h)
42  /// Strip any escapes
44  /// This is for everything else.
46 };
47 
49 public:
50  virtual ~dds_generator() = 0;
51 
52  static std::string get_tag_name(const std::string& base_name, const std::string& qualifier = "");
53 
54  static std::string get_xtag_name(UTL_ScopedName* name);
55 
56  static bool cxx_escaped(const std::string& s);
57 
58  static std::string valid_var_name(const std::string& str);
59 
60  virtual bool do_included_files() const { return false; }
61 
62  virtual void gen_prologue() {}
63 
64  virtual void gen_epilogue() {}
65 
66  virtual bool gen_const(UTL_ScopedName* /*name*/,
67  bool /*nestedInInteface*/,
68  AST_Constant* /*constant*/)
69  { return true; }
70 
71  virtual bool gen_enum(AST_Enum* /*node*/, UTL_ScopedName* /*name*/,
72  const std::vector<AST_EnumVal*>& /*contents*/,
73  const char* /*repoid*/)
74  { return true; }
75 
76  virtual bool gen_struct(AST_Structure* node, UTL_ScopedName* name,
77  const std::vector<AST_Field*>& fields,
78  AST_Type::SIZE_TYPE size,
79  const char* repoid) = 0;
80 
81  virtual bool gen_struct_fwd(UTL_ScopedName* /*name*/,
82  AST_Type::SIZE_TYPE /*size*/)
83  { return true; }
84 
85  virtual bool gen_typedef(AST_Typedef* node, UTL_ScopedName* name, AST_Type* base,
86  const char* repoid) = 0;
87 
88  virtual bool gen_interf(AST_Interface* /*node*/, UTL_ScopedName* /*name*/, bool /*local*/,
89  const std::vector<AST_Interface*>& /*inherits*/,
90  const std::vector<AST_Interface*>& /*inherits_flat*/,
91  const std::vector<AST_Attribute*>& /*attrs*/,
92  const std::vector<AST_Operation*>& /*ops*/,
93  const char* /*repoid*/)
94  { return true; }
95 
96  virtual bool gen_interf_fwd(UTL_ScopedName* /*name*/)
97  { return true; }
98 
99  virtual bool gen_native(AST_Native* /*node*/, UTL_ScopedName* /*name*/, const char* /*repoid*/)
100  { return true; }
101 
102  virtual bool gen_union(AST_Union* node, UTL_ScopedName* name,
103  const std::vector<AST_UnionBranch*>& branches,
104  AST_Type* discriminator,
105  const char* repoid) = 0;
106 
107  virtual bool gen_union_fwd(AST_UnionFwd* /*node*/, UTL_ScopedName* /*name*/,
108  AST_Type::SIZE_TYPE /*size*/)
109  { return true; }
110 
111  static std::string to_string(
113  static std::string scoped_helper(
114  UTL_ScopedName* sn, const char* sep, EscapeContext cxt = EscapeContext_Normal);
115  static std::string module_scope_helper(
116  UTL_ScopedName* sn, const char* sep, EscapeContext cxt = EscapeContext_Normal);
117 };
118 
119 inline std::string canonical_name(UTL_ScopedName* sn)
120 {
121  // NOTE: Names should not have leading "::" according to the XTypes spec.
123 }
124 
125 inline std::string canonical_name(Identifier* id)
126 {
128 }
129 
130 inline std::string canonical_name(AST_Decl* node)
131 {
132  return canonical_name(node->local_name());
133 }
134 
136 public:
137  void gen_prologue();
138 
139  void gen_epilogue();
140 
141  bool gen_const(UTL_ScopedName* name, bool nestedInInteface,
142  AST_Constant* constant);
143 
144  bool gen_enum(AST_Enum* node, UTL_ScopedName* name,
145  const std::vector<AST_EnumVal*>& contents, const char* repoid);
146 
147  bool gen_struct(AST_Structure* node, UTL_ScopedName* name,
148  const std::vector<AST_Field*>& fields,
149  AST_Type::SIZE_TYPE size, const char* repoid);
150 
151  bool gen_struct_fwd(UTL_ScopedName* name, AST_Type::SIZE_TYPE size);
152 
153  bool gen_typedef(AST_Typedef* node, UTL_ScopedName* name, AST_Type* base, const char* repoid);
154 
155  bool gen_interf(AST_Interface* node, UTL_ScopedName* name, bool local,
156  const std::vector<AST_Interface*>& inherits,
157  const std::vector<AST_Interface*>& inherits_flat,
158  const std::vector<AST_Attribute*>& attrs,
159  const std::vector<AST_Operation*>& ops, const char* repoid);
160 
161  bool gen_interf_fwd(UTL_ScopedName* name);
162 
163  bool gen_native(AST_Native* node, UTL_ScopedName* name, const char* repoid);
164 
165  bool gen_union(AST_Union* node, UTL_ScopedName* name,
166  const std::vector<AST_UnionBranch*>& branches,
167  AST_Type* discriminator,
168  const char* repoid);
169 
170  bool gen_union_fwd(AST_UnionFwd*, UTL_ScopedName* name, AST_Type::SIZE_TYPE size);
171 
172  composite_generator() : components_() {}
173 
174  template <typename InputIterator>
175  composite_generator(InputIterator begin, InputIterator end)
176  : components_(begin, end) {}
177 
178  void add_generator(dds_generator* gen) { components_.push_back(gen); }
179 
180 private:
181  std::vector<dds_generator*> components_;
182 };
183 
184 // common utilities for all "generator" derived classes
185 
187  const bool enabled_;
188  std::vector<std::string>* ns_;
189  std::vector<std::string> default_ns_;
190 
191  NamespaceGuard(bool enabled = true, std::vector<std::string>* ns = 0)
192  : enabled_(enabled)
193  , ns_(ns)
194  {
195  if (!ns_) {
196  default_ns_.push_back("OpenDDS");
197  default_ns_.push_back("DCPS");
198  ns_ = &default_ns_;
199  }
200  if (enabled_) {
201  std::string start_ns = "OPENDDS_BEGIN_VERSIONED_NAMESPACE_DECL\n";
202  for (size_t i = 0; i < ns_->size(); ++i) {
203  if (i > 0) {
204  start_ns += " ";
205  }
206  start_ns += "namespace " + (*ns_)[i] + " {";
207  }
208  start_ns += "\n\n";
209  be_global->header_ << start_ns;
210  be_global->impl_ << start_ns;
211  }
212  }
213 
215  {
216  if (enabled_) {
217  std::string end_ns;
218  for (size_t i = 0; i < ns_->size(); ++i) {
219  if (i > 0) {
220  end_ns += " ";
221  }
222  end_ns += "}";
223  }
224  end_ns += "\nOPENDDS_END_VERSIONED_NAMESPACE_DECL\n\n";
225  be_global->header_ << end_ns;
226  be_global->impl_ << end_ns;
227  }
228  }
229 };
230 
232  ScopedNamespaceGuard(UTL_ScopedName* name, std::ostream& os,
233  const char* keyword = "namespace")
234  : os_(os)
235  , semi_()
236  , n_(0)
237  {
238  const bool idl = !std::strcmp(keyword, "module");
240  for (n_ = 0; name->tail();
241  name = static_cast<UTL_ScopedName*>(name->tail())) {
242  const char* str = name->head()->get_string();
243  if (str && str[0]) {
244  ++n_;
245  os_ << keyword << ' ' << dds_generator::to_string(name->head(), ec) << " {\n";
246  }
247  }
248  if (idl) semi_ = ";";
249  }
250 
252  {
253  for (int i = 0; i < n_; ++i) os_ << '}' << semi_ << '\n';
254  }
255 
256  std::ostream& os_;
257  std::string semi_;
258  int n_;
259 };
260 
261 struct Function {
262  bool has_arg_;
263  std::string preamble_;
265 
266  Function(const std::string& name, const std::string returntype,
267  const char* template_args = 0)
268  : has_arg_(false)
269  , extra_newline_(true)
270  {
271  using std::string;
272  if (template_args) {
273  const string tmpl = string("template<") + template_args + "> ";
274  be_global->header_ << tmpl;
275  be_global->impl_ << tmpl;
276  }
277  ACE_CString ace_exporter = be_global->export_macro();
278  bool use_exp = ace_exporter != "";
279  string exporter = use_exp ? (string(" ") + ace_exporter.c_str()) : "";
280  be_global->header_ << ace_exporter << (use_exp ? "\n" : "")
281  << returntype << " " << name << "(";
282  be_global->impl_ << returntype << " " << name << "(";
283  }
284 
285  void addArg(const char* name, const std::string& type)
286  {
287  std::string sig = (has_arg_ ? ", " : "") + type + (name[0] ? " " : "")
288  + (name[0] ? name : "");
289  be_global->header_ << sig;
290  be_global->impl_ << sig;
291  if (name[0]) {
292  preamble_ += " ACE_UNUSED_ARG(" + std::string(name) + ");\n";
293  }
294  has_arg_ = true;
295  }
296 
297  void endArgs()
298  {
299  be_global->header_ << ");\n\n";
300  be_global->impl_ << ")\n{\n" << preamble_;
301  }
302 
304  {
305  be_global->impl_ << "}\n";
306  if (extra_newline_) {
307  be_global->impl_ << "\n";
308  }
309  }
310 };
311 
313 public:
315  const std::string& what,
316  bool impl = true, bool header = true,
317  const std::string& indent = "")
318  : what_(what)
319  , impl_(impl)
320  , header_(header)
321  , indent_(indent)
322  , extra_newline_(true)
323  {
324  output("#" + indent + "if" + what + "\n");
325  }
326 
328  {
329  output("#" + indent_ + "endif // if" + what_ + "\n");
330  if (extra_newline_) {
331  output("\n");
332  }
333  }
334 
335  void output(const std::string& str) const
336  {
337  if (impl_) {
338  be_global->impl_ << str;
339  }
340  if (header_) {
341  be_global->header_ << str;
342  }
343  }
344 
345  void extra_newline(bool value)
346  {
347  extra_newline_ = value;
348  }
349 
350 private:
351  const std::string what_;
352  const bool impl_;
353  const bool header_;
354  const std::string indent_;
356 };
357 
358 inline std::string scoped(UTL_ScopedName* sn, EscapeContext ec = EscapeContext_Normal)
359 {
360  // Add the leading scope operator here to make type names "fully-qualified" and avoid
361  // naming collisions with identifiers in OpenDDS::DCPS.
362  // The leading space allows this string to be used directly in a <>-delimeted template
363  // argument list while avoiding the <: digraph.
364  return " ::" + dds_generator::scoped_helper(sn, "::", ec);
365 }
366 
367 inline std::string module_scope(UTL_ScopedName* sn)
368 {
369  return dds_generator::module_scope_helper(sn, "::");
370 }
371 
373  inline AST_Type* resolveActualType(AST_Type* element)
374  {
375  if (element->node_type() == AST_Decl::NT_typedef) {
376  AST_Typedef* td = dynamic_cast<AST_Typedef*>(element);
377  return td->primitive_base_type();
378  }
379 
380  switch(element->node_type()) {
381  case AST_Decl::NT_interface_fwd:
382  {
383  AST_InterfaceFwd* td = dynamic_cast<AST_InterfaceFwd*>(element);
384  return td->full_definition();
385  }
386  case AST_Decl::NT_valuetype_fwd:
387  {
388  AST_ValueTypeFwd* td = dynamic_cast<AST_ValueTypeFwd*>(element);
389  return td->full_definition();
390  }
391  case AST_Decl::NT_union_fwd:
392  {
393  AST_UnionFwd* td = dynamic_cast<AST_UnionFwd*>(element);
394  return td->full_definition();
395  }
396  case AST_Decl::NT_struct_fwd:
397  {
398  AST_StructureFwd* td = dynamic_cast<AST_StructureFwd*>(element);
399  return td->full_definition();
400  }
401  case AST_Decl::NT_component_fwd:
402  {
403  AST_ComponentFwd* td = dynamic_cast<AST_ComponentFwd*>(element);
404  return td->full_definition();
405  }
406  case AST_Decl::NT_eventtype_fwd:
407  {
408  AST_EventTypeFwd* td = dynamic_cast<AST_EventTypeFwd*>(element);
409  return td->full_definition();
410  }
411  default:
412  return element;
413  }
414  }
415 
416  typedef size_t Classification;
417  const Classification CL_UNKNOWN = 0, CL_SCALAR = 1, CL_PRIMITIVE = 2,
418  CL_STRUCTURE = 4, CL_STRING = 8, CL_ENUM = 16, CL_UNION = 32, CL_ARRAY = 64,
419  CL_SEQUENCE = 128, CL_WIDE = 256, CL_BOUNDED = 512, CL_INTERFACE = 1024,
420  CL_FIXED = 2048;
421 
422  inline Classification classify(AST_Type* type)
423  {
424  type = resolveActualType(type);
425  switch (type->node_type()) {
426  case AST_Decl::NT_pre_defined: {
427  AST_PredefinedType* p = dynamic_cast<AST_PredefinedType*>(type);
428  switch (p->pt()) {
429  case AST_PredefinedType::PT_any:
430  case AST_PredefinedType::PT_object:
431  return CL_UNKNOWN;
432  case AST_PredefinedType::PT_wchar:
433  return CL_SCALAR | CL_PRIMITIVE | CL_WIDE;
434  default:
435  return CL_SCALAR | CL_PRIMITIVE;
436  }
437  }
438  case AST_Decl::NT_array:
439  return CL_ARRAY;
440  case AST_Decl::NT_union:
441  return CL_UNION;
442  case AST_Decl::NT_string:
443  case AST_Decl::NT_wstring:
444  return CL_SCALAR | CL_STRING |
445  ((dynamic_cast<AST_String*>(type)->max_size()->ev()->u.ulval == 0)
446  ? 0 : CL_BOUNDED) |
447  ((type->node_type() == AST_Decl::NT_wstring) ? CL_WIDE : 0);
448  case AST_Decl::NT_sequence:
449  return CL_SEQUENCE |
450  ((dynamic_cast<AST_Sequence*>(type)->unbounded()) ? 0 : CL_BOUNDED);
451  case AST_Decl::NT_struct:
452  return CL_STRUCTURE;
453  case AST_Decl::NT_enum:
454  return CL_SCALAR | CL_ENUM;
455  case AST_Decl::NT_interface:
456  return CL_INTERFACE;
457 #ifdef ACE_HAS_CDR_FIXED
458  case AST_Decl::NT_fixed:
459  return CL_FIXED;
460 #endif
461  default:
462  return CL_UNKNOWN;
463  }
464  }
465 }
466 
468  NestedForLoops(const char* type, const char* prefix, AST_Array* arr,
469  std::string& indent, bool followTypedefs = false);
470  ~NestedForLoops();
471 
472  size_t n_;
473  std::string& indent_;
474  std::string index_;
475 };
476 
478 
479 inline
480 std::string wrapPrefix(AST_Type* type, WrapDirection wd)
481 {
482  switch (type->node_type()) {
483  case AST_Decl::NT_pre_defined: {
484  AST_PredefinedType* const p = dynamic_cast<AST_PredefinedType*>(type);
485  switch (p->pt()) {
486  case AST_PredefinedType::PT_char:
487  return (wd == WD_OUTPUT)
488  ? "ACE_OutputCDR::from_char(" : "ACE_InputCDR::to_char(";
489  case AST_PredefinedType::PT_wchar:
490  return (wd == WD_OUTPUT)
491  ? "ACE_OutputCDR::from_wchar(" : "ACE_InputCDR::to_wchar(";
492  case AST_PredefinedType::PT_octet:
493  return (wd == WD_OUTPUT)
494  ? "ACE_OutputCDR::from_octet(" : "ACE_InputCDR::to_octet(";
495  case AST_PredefinedType::PT_boolean:
496  return (wd == WD_OUTPUT)
497  ? "ACE_OutputCDR::from_boolean(" : "ACE_InputCDR::to_boolean(";
498 #if OPENDDS_HAS_EXPLICIT_INTS
499  case AST_PredefinedType::PT_uint8:
500  return (wd == WD_OUTPUT)
501  ? "ACE_OutputCDR::from_uint8(" : "ACE_InputCDR::to_uint8(";
502  case AST_PredefinedType::PT_int8:
503  return (wd == WD_OUTPUT)
504  ? "ACE_OutputCDR::from_int8(" : "ACE_InputCDR::to_int8(";
505 #endif
506  default:
507  return "";
508  }
509  }
510  case AST_Decl::NT_string:
511  return (wd == WD_OUTPUT)
512  ? "ACE_OutputCDR::from_string(" : "ACE_InputCDR::to_string(";
513  case AST_Decl::NT_wstring:
514  return (wd == WD_OUTPUT)
515  ? "ACE_OutputCDR::from_wstring(" : "ACE_InputCDR::to_wstring(";
516  default:
517  return "";
518  }
519 }
520 
522 {
523  return be_global->language_mapping() == BE_GlobalData::LANGMAP_CXX11 ?
524  ((cls & AstTypeClassification::CL_WIDE) ? "std::wstring" : "std::string") :
525  (cls & AstTypeClassification::CL_WIDE) ? "TAO::WString_Manager" : "TAO::String_Manager";
526 }
527 
528 inline std::string to_cxx_type(AST_Type* type, std::size_t& size)
529 {
531  if (cls & AstTypeClassification::CL_ENUM) {
532  size = 4;
533  return "ACE_CDR::ULong";
534  }
536  return string_type(cls);
537  }
539  AST_Type* t = AstTypeClassification::resolveActualType(type);
540  AST_PredefinedType* p = dynamic_cast<AST_PredefinedType*>(t);
541  switch (p->pt()) {
542  case AST_PredefinedType::PT_long:
543  size = 4;
544  return "ACE_CDR::Long";
545  case AST_PredefinedType::PT_ulong:
546  size = 4;
547  return "ACE_CDR::ULong";
548  case AST_PredefinedType::PT_longlong:
549  size = 8;
550  return "ACE_CDR::LongLong";
551  case AST_PredefinedType::PT_ulonglong:
552  size = 8;
553  return "ACE_CDR::ULongLong";
554  case AST_PredefinedType::PT_short:
555  size = 2;
556  return "ACE_CDR::Short";
557  case AST_PredefinedType::PT_ushort:
558  size = 2;
559  return "ACE_CDR::UShort";
560 #if OPENDDS_HAS_EXPLICIT_INTS
561  case AST_PredefinedType::PT_int8:
562  size = 1;
563  return "ACE_CDR::Int8";
564  case AST_PredefinedType::PT_uint8:
565  size = 1;
566  return "ACE_CDR::UInt8";
567 #endif
568  case AST_PredefinedType::PT_float:
569  size = 4;
570  return "ACE_CDR::Float";
571  case AST_PredefinedType::PT_double:
572  size = 8;
573  return "ACE_CDR::Double";
574  case AST_PredefinedType::PT_longdouble:
575  size = 16;
576  return "ACE_CDR::LongDouble";
577  case AST_PredefinedType::PT_char:
578  size = 1;
579  return "ACE_CDR::Char";
580  case AST_PredefinedType::PT_wchar:
581  size = 2;
582  return "ACE_CDR::WChar";
583  case AST_PredefinedType::PT_boolean:
584  size = 1;
585  return "ACE_CDR::Boolean";
586  case AST_PredefinedType::PT_octet:
587  size = 1;
588  return "ACE_CDR::Octet";
589  case AST_PredefinedType::PT_any:
590  case AST_PredefinedType::PT_object:
591  case AST_PredefinedType::PT_value:
592  case AST_PredefinedType::PT_abstract:
593  case AST_PredefinedType::PT_void:
594  case AST_PredefinedType::PT_pseudo:
595  be_util::misc_error_and_abort("Unsupported predefined type in to_cxx_type");
596  }
597  be_util::misc_error_and_abort("Unhandled predefined type in to_cxx_type");
598  }
599  return scoped(type->name());
600 }
601 
602 inline
603 std::string getWrapper(const std::string& name, AST_Type* type, WrapDirection wd)
604 {
605  using namespace AstTypeClassification;
606  if (be_global->language_mapping() == BE_GlobalData::LANGMAP_CXX11) {
607  const Classification cls = classify(type);
608  if ((cls & (CL_BOUNDED | CL_STRING)) == (CL_BOUNDED | CL_STRING)) {
609  return (wd == WD_OUTPUT ? "Serializer::FromBoundedString" : "Serializer::ToBoundedString")
610  + std::string(cls & CL_WIDE ? "<wchar_t>(" : "<char>(") + name + ')';
611  }
612  }
613  std::string pre = wrapPrefix(type, wd);
614  return (pre.empty()) ? name : (pre + name + ')');
615 }
616 
617 inline
618 std::string getEnumLabel(AST_Expression* label_val, AST_Type* disc)
619 {
620  std::string e = scoped(disc->name()),
621  label = label_val->n()->last_component()->get_string();
622  if (be_global->language_mapping() == BE_GlobalData::LANGMAP_CXX11) {
623  return e + "::" + label;
624  }
625  const size_t colon = e.rfind("::");
626  if (colon == std::string::npos) {
627  return label;
628  }
629  return e.replace(colon + 2, std::string::npos, label);
630 }
631 
632 inline
633 std::ostream& operator<<(std::ostream& o,
634  const AST_Expression::AST_ExprValue& ev)
635 {
636  using namespace OpenDDS::DCPS;
637  RestoreOutputStreamState ross(o);
638  switch (ev.et) {
639  case AST_Expression::EV_octet:
640  return hex_value(o << "0x", static_cast<int>(ev.u.oval), 1);
641 #if OPENDDS_HAS_EXPLICIT_INTS
642  case AST_Expression::EV_int8:
643  return o << static_cast<short>(ev.u.int8val);
644  case AST_Expression::EV_uint8:
645  return o << static_cast<unsigned short>(ev.u.uint8val);
646 #endif
647  case AST_Expression::EV_short:
648  return o << ev.u.sval;
649  case AST_Expression::EV_ushort:
650  return o << ev.u.usval << 'u';
651  case AST_Expression::EV_long:
652  return signed_int_helper<ACE_CDR::Long>(o, ev.u.lval, ACE_INT32_MIN);
653  case AST_Expression::EV_ulong:
654  return o << ev.u.ulval << 'u';
655  case AST_Expression::EV_longlong:
656  return signed_int_helper<ACE_CDR::LongLong>(o, ev.u.llval, ACE_INT64_MIN) << "LL";
657  case AST_Expression::EV_ulonglong:
658  return o << ev.u.ullval << "ULL";
659  case AST_Expression::EV_wchar:
660  return char_helper<ACE_CDR::WChar>(o << "L'", ev.u.wcval) << '\'';
661  case AST_Expression::EV_char:
662  return char_helper<ACE_CDR::Char>(o << '\'', ev.u.cval) << '\'';
663  case AST_Expression::EV_bool:
664  return o << std::boolalpha << static_cast<bool>(ev.u.bval);
665  case AST_Expression::EV_float:
666  return o << ev.u.fval << 'f';
667  case AST_Expression::EV_double:
668  return o << ev.u.dval;
669  case AST_Expression::EV_wstring:
670  return o << "L\"" << ev.u.wstrval << '"';
671  case AST_Expression::EV_string:
672  return o << '"' << ev.u.strval->get_string() << '"';
673 #ifdef ACE_HAS_CDR_FIXED
674  case AST_Expression::EV_fixed: {
676  ev.u.fixedval.to_string(buf, sizeof buf);
677  return o << "\"" << buf << "\"";
678  }
679 #endif
680  case AST_Expression::EV_enum:
681  case AST_Expression::EV_longdouble:
682  case AST_Expression::EV_any:
683  case AST_Expression::EV_object:
684  case AST_Expression::EV_void:
685  case AST_Expression::EV_none:
687  "Unsupported ExprType value in operator<<(std::ostream, AST_ExprValue)");
688  }
690  "Unhandled ExprType value in operator<<(std::ostream, AST_ExprValue)");
691  return o;
692 }
693 
694 inline std::string bounded_arg(AST_Type* type)
695 {
696  using namespace AstTypeClassification;
697  std::ostringstream arg;
698  const Classification cls = classify(type);
699  if (cls & CL_STRING) {
700  AST_String* const str = dynamic_cast<AST_String*>(type);
701  arg << str->max_size()->ev()->u.ulval;
702  } else if (cls & CL_SEQUENCE) {
703  AST_Sequence* const seq = dynamic_cast<AST_Sequence*>(type);
704  arg << seq->max_size()->ev()->u.ulval;
705  }
706  return arg.str();
707 }
708 
709 std::string type_to_default(const std::string& indent, AST_Type* type,
710  const std::string& name, bool is_anonymous = false, bool is_union = false);
711 
712 inline
713 void generateBranchLabels(AST_UnionBranch* branch, AST_Type* discriminator,
714  size_t& n_labels, bool& has_default)
715 {
716  for (unsigned long j = 0; j < branch->label_list_length(); ++j) {
717  ++n_labels;
718  AST_UnionLabel* label = branch->label(j);
719  if (label->label_kind() == AST_UnionLabel::UL_default) {
720  be_global->impl_ << " default:";
721  has_default = true;
722  } else if (discriminator->node_type() == AST_Decl::NT_enum) {
723  be_global->impl_ << " case "
724  << getEnumLabel(label->label_val(), discriminator) << ':';
725  } else {
726  be_global->impl_ << " case " << *label->label_val()->ev() << ':';
727  }
728  be_global->impl_<< ((j == branch->label_list_length() - 1) ? " {\n" : "\n");
729  }
730 }
731 
732 // see TAO_IDL_BE be_union::gen_empty_default_label()
733 inline bool needSyntheticDefault(AST_Type* disc, size_t n_labels)
734 {
735  AST_Decl::NodeType nt = disc->node_type();
736  if (nt == AST_Decl::NT_enum) return true;
737 
738  AST_PredefinedType* pdt = dynamic_cast<AST_PredefinedType*>(disc);
739  switch (pdt->pt()) {
740  case AST_PredefinedType::PT_boolean:
741  return n_labels < 2;
742 #if OPENDDS_HAS_EXPLICIT_INTS
743  case AST_PredefinedType::PT_int8:
744  case AST_PredefinedType::PT_uint8:
745 #endif
746  case AST_PredefinedType::PT_char:
747  case AST_PredefinedType::PT_octet:
748  return n_labels < ACE_OCTET_MAX;
749  case AST_PredefinedType::PT_short:
750  case AST_PredefinedType::PT_ushort:
751  case AST_PredefinedType::PT_wchar:
752  return n_labels < ACE_UINT16_MAX;
753  case AST_PredefinedType::PT_long:
754  case AST_PredefinedType::PT_ulong:
755  return n_labels < ACE_UINT32_MAX;
756  default:
757  return true;
758  }
759 }
760 
761 struct Intro {
762  typedef std::set<std::string> LineSet;
763  LineSet line_set;
764  typedef std::vector<std::string> LineVec;
765  LineVec line_vec;
766 
767  void join(std::ostream& os, const std::string& indent)
768  {
769  for (LineVec::iterator i = line_vec.begin(); i != line_vec.end(); ++i) {
770  os << indent << *i << '\n';
771  }
772  }
773 
774  void insert(const std::string& line)
775  {
776  if (line_set.insert(line).second) {
777  line_vec.push_back(line);
778  }
779  }
780 
781  void insert(const Intro& other)
782  {
783  for (LineVec::const_iterator i = other.line_vec.begin(); i != other.line_vec.end(); ++i) {
784  insert(*i);
785  }
786  }
787 };
788 
789 std::string field_type_name(AST_Field* field, AST_Type* field_type = 0);
790 
791 /**
792  * For the some situations, like a tag name, the type name we need is the
793  * deepest named type, not the actual type. This will be the name of the
794  * deepest typedef if it's an array or sequence, otherwise the name of the
795  * type.
796  */
797 AST_Type* deepest_named_type(AST_Type* type);
798 
799 typedef std::string (*CommonFn)(
800  const std::string& indent, AST_Decl* node,
801  const std::string& name, AST_Type* type,
802  const std::string& prefix, bool wrap_nested_key_only, Intro& intro,
803  const std::string&);
804 
805 inline
807  CommonFn commonFn, CommonFn commonFn2,
808  AST_UnionBranch* branch,
809  const char* statementPrefix, const char* namePrefix, const char* uni, bool generateBreaks, bool parens)
810 {
811  using namespace AstTypeClassification;
812  const BE_GlobalData::LanguageMapping lmap = be_global->language_mapping();
813  const bool use_cxx11 = lmap == BE_GlobalData::LANGMAP_CXX11;
814  const std::string name = branch->local_name()->get_string();
815  if (namePrefix == std::string(">> ")) {
816  std::string brType = field_type_name(branch, branch->field_type());
817  std::string forany;
818  AST_Type* br = resolveActualType(branch->field_type());
819  Classification br_cls = classify(br);
820  if (!br->in_main_file()
821  && br->node_type() != AST_Decl::NT_pre_defined) {
822  be_global->add_referenced(br->file_name().c_str());
823  }
824 
825  std::string rhs;
826  const bool is_face = lmap == BE_GlobalData::LANGMAP_FACE_CXX;
827  const bool is_wide = br_cls & CL_WIDE;
828  const bool is_bound_string = (br_cls & (CL_STRING | CL_BOUNDED)) == (CL_STRING | CL_BOUNDED);
829  const std::string bound_string_suffix = (is_bound_string && !is_face) ? ".c_str()" : "";
830 
831  if (is_bound_string) {
832  const std::string to_type = is_face ? is_wide ? "ACE_InputCDR::to_wstring" : "ACE_InputCDR::to_string"
833  : is_wide ? "Serializer::ToBoundedString<wchar_t>" : "Serializer::ToBoundedString<char>";
834  const std::string face_suffix = is_face ? ".out()" : "";
835  brType = is_face ? is_wide ? "FACE::WString_var" : "FACE::String_var"
836  : is_wide ? "OPENDDS_WSTRING" : "OPENDDS_STRING";
837  rhs = to_type + "(tmp" + face_suffix + ", " + bounded_arg(br) + ")";
838  } else if (br_cls & CL_STRING) {
839  const std::string nmspace = is_face ? "FACE::" : "CORBA::";
840  brType = use_cxx11 ? std::string("std::") + (is_wide ? "w" : "") + "string"
841  : nmspace + (is_wide ? "W" : "") + "String_var";
842  rhs = use_cxx11 ? "tmp" : "tmp.out()";
843  } else if (use_cxx11 && (br_cls & (CL_ARRAY | CL_SEQUENCE))) { //array or seq C++11
844  rhs = "IDL::DistinctType<" + brType + ", "
846  + ">(tmp)";
847  } else if (br_cls & CL_ARRAY) { //array classic
848  forany = " " + brType + "_forany fa = tmp;\n";
849  rhs = getWrapper("fa", br, WD_INPUT);
850  } else { // anything else
851  rhs = getWrapper("tmp", br, WD_INPUT);
852  }
853 
854  if (*statementPrefix) {
855  be_global->impl_ << statementPrefix;
856  }
857  be_global->impl_ <<
858  " " << brType << " tmp;\n" << forany <<
859  " if (strm >> " << rhs << ") {\n"
860  " uni." << name << (use_cxx11 ? "(std::move(tmp));\n" : "(tmp" + bound_string_suffix + ");\n") <<
861  " uni._d(disc);\n"
862  " return true;\n"
863  " }\n";
864 
865  if (be_global->try_construct(branch) == tryconstructfailaction_use_default) {
866  be_global->impl_ <<
867  type_to_default(" ", br, "uni." + name, branch->anonymous(), true) <<
868  " strm.set_construction_status(Serializer::ConstructionSuccessful);\n"
869  " return true;\n";
870  } else if ((be_global->try_construct(branch) == tryconstructfailaction_trim) && (br_cls & CL_BOUNDED) &&
871  (br_cls & (CL_STRING | CL_SEQUENCE))) {
872  if (is_bound_string) {
873  const std::string check_not_empty = "!tmp.empty()";
874  const std::string get_length = use_cxx11 ? "tmp.length()" : "ACE_OS::strlen(tmp.c_str())";
875  const std::string inout = use_cxx11 ? "" : ".inout()";
876  const std::string strtype = br_cls & CL_WIDE ? "std::wstring" : "std::string";
877  be_global->impl_ <<
878  " if (strm.get_construction_status() == Serializer::BoundConstructionFailure && " << check_not_empty << " && ("
879  << bounded_arg(br) << " < " << get_length << ")) {\n"
880  " " << strtype << " s = tmp.c_str();\n"
881  " s.resize(" << bounded_arg(br) << ");\n"
882  " uni." << name << "(s.c_str());\n"
883  " strm.set_construction_status(Serializer::ConstructionSuccessful);\n"
884  " return true;\n"
885  " } else {\n"
886  " strm.set_construction_status(Serializer::ElementConstructionFailure);\n"
887  " return false;\n"
888  " }\n";
889  } else if (br_cls & CL_SEQUENCE) {
890  be_global->impl_ <<
891  " if(strm.get_construction_status() == Serializer::ElementConstructionFailure) {\n"
892  " return false;\n"
893  " }\n"
894  " uni." << name << (use_cxx11 ? "(std::move(tmp));\n" : "(tmp);\n") <<
895  " uni._d(disc);\n"
896  " strm.set_construction_status(Serializer::ConstructionSuccessful);\n"
897  " return true;\n";
898  }
899  } else {
900  //discard/default
901  be_global->impl_ <<
902  " strm.set_construction_status(Serializer::ElementConstructionFailure);\n"
903  " return false;\n ";
904  }
905  } else {
906  const char* breakString = generateBreaks ? " break;\n" : "";
907  const std::string indent = " ";
908  Intro intro;
909  std::ostringstream contents;
910  if (commonFn2) {
911  const OpenDDS::XTypes::MemberId id = be_global->get_id(branch);
912  contents
913  << commonFn2(indent, branch, name + (parens ? "()" : ""), branch->field_type(), "uni", false, intro, "")
914  << indent << "if (!strm.write_parameter_id(" << id << ", size)) {\n"
915  << indent << " return false;\n"
916  << indent << "}\n";
917  }
918  const std::string expr = commonFn(indent, branch,
919  name + (parens ? "()" : ""), branch->field_type(),
920  std::string(namePrefix) + "uni", false, intro, uni);
921  if (*statementPrefix) {
922  contents <<
923  indent << statementPrefix << " " << expr << ";\n" <<
924  (statementPrefix == std::string("return") ? "" : breakString);
925  } else {
926  contents << expr << breakString;
927  }
928  intro.join(be_global->impl_, indent);
929  be_global->impl_ << contents.str();
930  }
931 }
932 
933 inline
934 bool generateSwitchBody(AST_Union*, CommonFn commonFn,
935  const std::vector<AST_UnionBranch*>& branches,
936  AST_Type* discriminator, const char* statementPrefix,
937  const char* namePrefix = "", const char* uni = "",
938  bool forceDisableDefault = false, bool parens = true,
939  bool breaks = true, CommonFn commonFn2 = 0)
940 {
941  size_t n_labels = 0;
942  bool has_default = false;
943  for (size_t i = 0; i < branches.size(); ++i) {
944  AST_UnionBranch* branch = branches[i];
945  if (forceDisableDefault) {
946  bool foundDefault = false;
947  for (unsigned long j = 0; j < branch->label_list_length(); ++j) {
948  if (branch->label(j)->label_kind() == AST_UnionLabel::UL_default) {
949  foundDefault = true;
950  }
951  }
952  if (foundDefault) {
953  has_default = true;
954  continue;
955  }
956  }
957  generateBranchLabels(branch, discriminator, n_labels, has_default);
958  generateCaseBody(commonFn, commonFn2, branch, statementPrefix, namePrefix,
959  uni, breaks, parens);
960  be_global->impl_ <<
961  " }\n";
962  }
963  if (!has_default && needSyntheticDefault(discriminator, n_labels)) {
964  be_global->impl_ <<
965  " default:\n" <<
966  ((namePrefix == std::string(">> ")) ? " uni._d(disc);\n" : "") <<
967  " break;\n";
968  return true;
969  }
970  return false;
971 }
972 
973 /// returns true if a default: branch was generated (no default: label in IDL)
974 inline
975 bool generateSwitchForUnion(AST_Union* u, const char* switchExpr, CommonFn commonFn,
976  const std::vector<AST_UnionBranch*>& branches,
977  AST_Type* discriminator, const char* statementPrefix,
978  const char* namePrefix = "", const char* uni = "",
979  bool forceDisableDefault = false, bool parens = true,
980  bool breaks = true, CommonFn commonFn2 = 0)
981 {
982  using namespace AstTypeClassification;
983  AST_Type* dt = resolveActualType(discriminator);
984  AST_PredefinedType* bt = dynamic_cast<AST_PredefinedType*>(dt);
985  if (bt && bt->pt() == AST_PredefinedType::PT_boolean) {
986  AST_UnionBranch* true_branch = 0;
987  AST_UnionBranch* false_branch = 0;
988  AST_UnionBranch* default_branch = 0;
989  for (std::vector<AST_UnionBranch*>::const_iterator pos = branches.begin(),
990  limit = branches.end(); pos != limit; ++pos) {
991  AST_UnionBranch* branch = *pos;
992  for (unsigned long j = 0; j < branch->label_list_length(); ++j) {
993  AST_UnionLabel* label = branch->label(j);
994  if (label->label_kind() == AST_UnionLabel::UL_default) {
995  default_branch = branch;
996  } else if (label->label_val()->ev()->u.bval) {
997  true_branch = branch;
998  } else if (!label->label_val()->ev()->u.bval) {
999  false_branch = branch;
1000  }
1001  }
1002  }
1003 
1004  if (true_branch || false_branch) {
1005  be_global->impl_ <<
1006  " if (" << switchExpr << ") {\n";
1007  } else {
1008  be_global->impl_ <<
1009  " {\n";
1010  }
1011 
1012  if (true_branch || default_branch) {
1013  generateCaseBody(commonFn, commonFn2, true_branch ? true_branch : default_branch,
1014  statementPrefix, namePrefix, uni, false, parens);
1015  }
1016 
1017  if (false_branch || (default_branch && true_branch)) {
1018  be_global->impl_ <<
1019  " } else {\n";
1020  generateCaseBody(commonFn, commonFn2, false_branch ? false_branch : default_branch,
1021  statementPrefix, namePrefix, uni, false, parens);
1022  }
1023 
1024  be_global->impl_ <<
1025  " }\n";
1026 
1027  return !default_branch && bool(true_branch) != bool(false_branch);
1028 
1029  } else {
1030  be_global->impl_ <<
1031  " switch (" << switchExpr << ") {\n";
1032  bool b(generateSwitchBody(u, commonFn, branches, discriminator,
1033  statementPrefix, namePrefix, uni,
1034  forceDisableDefault, parens, breaks,
1035  commonFn2));
1036  be_global->impl_ <<
1037  " }\n";
1038  return b;
1039  }
1040 }
1041 
1042 inline
1044  const std::string& full_var_name_, bool is_union_member = false)
1045 {
1046  const bool use_cxx11 = be_global->language_mapping() == BE_GlobalData::LANGMAP_CXX11;
1047  if (!use_cxx11 || is_union_member || full_var_name_.empty()) {
1048  return full_var_name_;
1049  }
1050 
1051  std::string full_var_name(full_var_name_);
1052  std::string::size_type n = 0;
1053  while ((n = full_var_name.find('.', n)) != std::string::npos) {
1054  if (full_var_name[n-1] != ']') {
1055  full_var_name.insert(n, "()");
1056  n += 3;
1057  } else {
1058  ++n;
1059  }
1060  }
1061  n = 0;
1062  while ((n = full_var_name.find('[', n)) != std::string::npos) {
1063  full_var_name.insert(n, "()");
1064  n += 3;
1065  }
1066  return full_var_name[full_var_name.size() - 1] == ']'
1067  ? full_var_name : full_var_name + "()";
1068 }
1069 
1074 };
1075 
1076 inline
1077 AST_Field* get_struct_field(AST_Structure* struct_node, unsigned index)
1078 {
1079  if (!struct_node || index >= struct_node->nfields()) {
1080  return 0;
1081  }
1082  AST_Field** field_ptrptr;
1083  struct_node->field(field_ptrptr, index);
1084  return field_ptrptr ? *field_ptrptr : 0;
1085 }
1086 
1087 inline
1088 bool struct_has_explicit_keys(AST_Structure* node)
1089 {
1090  for (unsigned i = 0; i < node->nfields(); ++i) {
1091  if (be_global->is_key(get_struct_field(node, i))) {
1092  return true;
1093  }
1094  }
1095  return false;
1096 }
1097 
1098 /**
1099  * Wrapper for Iterating Over Structure Fields
1100  */
1101 class Fields {
1102 public:
1103  class Iterator {
1104  public:
1105  typedef AST_Field* value_type;
1106  typedef AST_Field** pointer;
1107  typedef AST_Field*& reference;
1108  typedef std::input_iterator_tag iterator_category;
1109 
1110  explicit Iterator(AST_Structure* node = 0, unsigned pos = 0, bool explicit_keys_only = false)
1111  : node_(node)
1112  , pos_(pos)
1113  , explicit_keys_only_(explicit_keys_only)
1114  {
1115  validate_pos();
1116  }
1117 
1118  bool valid() const
1119  {
1120  return node_ && pos_ < node_->nfields();
1121  }
1122 
1123  bool check()
1124  {
1125  if (!valid()) {
1126  if (node_) {
1127  *this = Iterator();
1128  }
1129  return false;
1130  }
1131  return true;
1132  }
1133 
1135  {
1136  for (; check() && explicit_keys_only_ && !be_global->is_key(**this); ++pos_) {
1137  }
1138  }
1139 
1140  unsigned pos() const
1141  {
1142  return pos_;
1143  }
1144 
1145  Iterator& operator++() // Prefix
1146  {
1147  ++pos_;
1148  validate_pos();
1149  return *this;
1150  }
1151 
1152  Iterator operator++(int) // Postfix
1153  {
1154  Iterator prev(*this);
1155  ++(*this);
1156  return prev;
1157  }
1158 
1159  AST_Field* operator*() const
1160  {
1161  return get_struct_field(node_, pos_);
1162  }
1163 
1164  bool operator==(const Iterator& other) const
1165  {
1166  return node_ == other.node_
1167  && pos_ == other.pos_
1168  && explicit_keys_only_ == other.explicit_keys_only_;
1169  }
1170 
1171  bool operator!=(const Iterator& other) const
1172  {
1173  return !(*this == other);
1174  }
1175 
1176  private:
1177  AST_Structure* node_;
1178  unsigned pos_;
1180  };
1181 
1182  explicit Fields(AST_Structure* node = 0, FieldFilter filter = FieldFilter_All)
1183  : node_(node)
1184  , explicit_keys_only_(explicit_keys_only(node, filter))
1185  {
1186  }
1187 
1188  static bool explicit_keys_only(AST_Structure* node, FieldFilter filter)
1189  {
1190  return filter == FieldFilter_KeyOnly ||
1191  (filter == FieldFilter_NestedKeyOnly && node && struct_has_explicit_keys(node));
1192  }
1193 
1194  AST_Structure* node() const
1195  {
1196  return node_;
1197  }
1198 
1199  Iterator begin() const
1200  {
1201  return Iterator(node_, 0, explicit_keys_only_);
1202  }
1203 
1204  Iterator end() const
1205  {
1206  static Iterator end_value;
1207  return end_value;
1208  }
1209 
1210  Iterator operator[](unsigned position) const
1211  {
1212  return Iterator(node_, position);
1213  }
1214 
1215 private:
1216  AST_Structure* const node_;
1218 };
1219 
1220 inline
1222 {
1223  ACE_CDR::ULong count = 1;
1224  for (ACE_CDR::ULong i = 0; i < arr->n_dims(); ++i) {
1225  count *= arr->dims()[i]->ev()->u.ulval;
1226  }
1227  return count;
1228 }
1229 
1230 inline
1232 {
1233  AST_Type* const act = AstTypeClassification::resolveActualType(type);
1234  AST_Sequence* const seq = dynamic_cast<AST_Sequence*>(act);
1235  AST_Array* const arr = dynamic_cast<AST_Array*>(act);
1236  if (seq && !seq->unbounded()) {
1237  return seq->max_size()->ev()->u.ulval;
1238  } else if (arr) {
1239  return array_element_count(arr);
1240  }
1241  return 0;
1242 }
1243 
1244 inline
1245 AST_Type* container_base_type(AST_Type* type)
1246 {
1247  AST_Type* const act = AstTypeClassification::resolveActualType(type);
1248  AST_Sequence* const seq = dynamic_cast<AST_Sequence*>(act);
1249  AST_Array* const arr = dynamic_cast<AST_Array*>(act);
1250  if (seq) {
1251  return seq->base_type();
1252  } else if (arr) {
1253  return arr->base_type();
1254  }
1255  return 0;
1256 }
1257 
1258 /**
1259  * Returns true for a type if nested key serialization is different from
1260  * normal serialization.
1261  */
1262 inline bool needs_nested_key_only(AST_Type* type)
1263 {
1264  AST_Type* const non_aliased_type = type;
1265 
1266  using namespace AstTypeClassification;
1267 
1268  static std::vector<AST_Type*> type_stack;
1269  type = resolveActualType(type);
1270  // Check if we have encountered the same type recursively
1271  for (size_t i = 0; i < type_stack.size(); ++i) {
1272  if (type == type_stack[i]) {
1273  return true;
1274  }
1275  }
1276  type_stack.push_back(type);
1277 
1278  bool result = false;
1279  const std::string name = scoped(type->name());
1280 
1281  std::string template_name;
1282  if (be_global->special_serialization(non_aliased_type, template_name)) {
1283  result = false;
1284  } else {
1285  const Classification type_class = classify(type);
1286  if (type_class & CL_ARRAY) {
1287  result = needs_nested_key_only(dynamic_cast<AST_Array*>(type)->base_type());
1288  } else if (type_class & CL_SEQUENCE) {
1289  result = needs_nested_key_only(dynamic_cast<AST_Sequence*>(type)->base_type());
1290  } else if (type_class & CL_STRUCTURE) {
1291  AST_Structure* const struct_node = dynamic_cast<AST_Structure*>(type);
1292  // TODO(iguessthislldo): Possible optimization: If everything in a struct
1293  // was a key recursively, then we could return false.
1294  if (struct_has_explicit_keys(struct_node)) {
1295  result = true;
1296  } else {
1297  const Fields fields(struct_node);
1298  const Fields::Iterator fields_end = fields.end();
1299  for (Fields::Iterator i = fields.begin(); i != fields_end; ++i) {
1300  if (needs_nested_key_only((*i)->field_type())) {
1301  result = true;
1302  break;
1303  }
1304  }
1305  }
1306  } else if (type_class & CL_UNION) {
1307  // A union will always be different as a key because it's just the
1308  // discriminator.
1309  result = true;
1310  }
1311  }
1312  type_stack.pop_back();
1313  return result;
1314 }
1315 
1316 inline bool needs_forany(AST_Type* type)
1317 {
1318  using namespace AstTypeClassification;
1319  const Classification type_class = classify(resolveActualType(type));
1320  return be_global->language_mapping() != BE_GlobalData::LANGMAP_CXX11 &&
1321  type_class & CL_ARRAY;
1322 }
1323 
1324 inline bool needs_distinct_type(AST_Type* type)
1325 {
1326  using namespace AstTypeClassification;
1327  const Classification type_class = classify(resolveActualType(type));
1328  return be_global->language_mapping() == BE_GlobalData::LANGMAP_CXX11 &&
1329  type_class & (CL_SEQUENCE | CL_ARRAY);
1330 }
1331 
1332 const char* const shift_out = "<< ";
1333 const char* const shift_in = ">> ";
1334 
1335 inline std::string strip_shift_op(const std::string& s)
1336 {
1337  const size_t shift_len = 3;
1338  std::string rv = s;
1339  if (rv.size() > shift_len) {
1340  const std::string first3 = rv.substr(0, shift_len);
1341  if (first3 == shift_out || first3 == shift_in) {
1342  rv.erase(0, 3);
1343  }
1344  }
1345  return rv;
1346 }
1347 
1348 inline const char* get_shift_op(const std::string& s)
1349 {
1350  const size_t shift_len = 3;
1351  if (s.size() > shift_len) {
1352  const std::string first3 = s.substr(0, shift_len);
1353  if (first3 == shift_in) {
1354  return shift_in;
1355  }
1356  if (first3 == shift_out) {
1357  return shift_out;
1358  }
1359  }
1360  return "";
1361 }
1362 
1363 /// Handling wrapping and unwrapping references in the wrapper types:
1364 /// NestedKeyOnly, IDL::DistinctType, and *_forany.
1365 struct RefWrapper {
1366  const bool cpp11_;
1367  AST_Type* const type_;
1368  const std::string type_name_;
1369  const std::string to_wrap_;
1370  const char* const shift_op_;
1371  const std::string fieldref_;
1372  const std::string local_;
1378  AST_Typedef* typedef_node_;
1379 
1380  RefWrapper(AST_Type* type, const std::string& type_name,
1381  const std::string& to_wrap, bool is_const = true)
1382  : cpp11_(be_global->language_mapping() == BE_GlobalData::LANGMAP_CXX11)
1383  , type_(type)
1384  , type_name_(type_name)
1385  , to_wrap_(strip_shift_op(to_wrap))
1386  , shift_op_(get_shift_op(to_wrap))
1387  , is_const_(is_const)
1388  , nested_key_only_(false)
1389  , classic_array_copy_(false)
1390  , dynamic_data_adapter_(false)
1391  , typedef_node_(0)
1392  , done_(false)
1393  {
1394  }
1395 
1396  RefWrapper(AST_Type* type, const std::string& type_name,
1397  const std::string& fieldref, const std::string& local, bool is_const = true)
1398  : cpp11_(be_global->language_mapping() == BE_GlobalData::LANGMAP_CXX11)
1399  , type_(type)
1400  , type_name_(type_name)
1401  , shift_op_("")
1402  , fieldref_(strip_shift_op(fieldref))
1403  , local_(local)
1404  , is_const_(is_const)
1405  , nested_key_only_(false)
1406  , classic_array_copy_(false)
1407  , dynamic_data_adapter_(false)
1408  , typedef_node_(0)
1409  , done_(false)
1410  {
1411  }
1412 
1413  RefWrapper& done(Intro* intro = 0)
1414  {
1415  ACE_ASSERT(!done_);
1416 
1417  if (is_const_ && !std::strcmp(shift_op_, shift_in)) {
1418  is_const_ = false;
1419  }
1420  const std::string const_str = is_const_ ? "const " : "";
1421  const bool forany = classic_array_copy_ || needs_forany(type_);
1422  const bool distinct_type = needs_distinct_type(type_);
1423  needs_dda_tag_ = dynamic_data_adapter_ && (forany || distinct_type);
1424  nested_key_only_ = nested_key_only_ &&
1425  needs_nested_key_only(typedef_node_ ? typedef_node_ : type_);
1426  wrapped_type_name_ = type_name_;
1427  bool by_ref = true;
1428 
1429  if (to_wrap_.size()) {
1430  ref_ = to_wrap_;
1431  } else {
1432  ref_ = fieldref_;
1433  if (local_.size()) {
1434  ref_ += '.' + local_;
1435  }
1436  }
1437 
1438  if (forany && !dynamic_data_adapter_) {
1439  const std::string forany_type = type_name_ + "_forany";
1440  if (classic_array_copy_) {
1441  const std::string var_name = dds_generator::valid_var_name(ref_) + "_tmp_var";
1442  classic_array_copy_var_ = var_name;
1443  if (intro) {
1444  intro->insert(type_name_ + "_var " + var_name + "= " + type_name_ + "_alloc();");
1445  }
1446  ref_ = var_name;
1447  }
1448  const std::string var_name = dds_generator::valid_var_name(ref_) + "_forany";
1449  wrapped_type_name_ = forany_type;
1450  if (intro) {
1451  std::string line = forany_type + " " + var_name;
1452  if (classic_array_copy_) {
1453  line += " = " + ref_ + ".inout();";
1454  } else {
1455  line += "(const_cast<" + type_name_ + "_slice*>(" + ref_ + "));";
1456  }
1457  intro->insert(line);
1458  }
1459  ref_ = var_name;
1460  }
1461 
1462  if (nested_key_only_) {
1463  wrapped_type_name_ =
1464  std::string("NestedKeyOnly<") + const_str + wrapped_type_name_ + ">";
1465  value_access_post_ = ".value" + value_access_post_;
1466  const std::string nko_arg = "(" + ref_ + ")";
1467  if (is_const_) {
1468  ref_ = wrapped_type_name_ + nko_arg;
1469  } else {
1470  ref_ = dds_generator::valid_var_name(ref_) + "_nested_key_only";
1471  if (intro) {
1472  intro->insert(wrapped_type_name_ + " " + ref_ + nko_arg + ";");
1473  }
1474  }
1475  }
1476 
1477  if (distinct_type && !dynamic_data_adapter_) {
1478  wrapped_type_name_ =
1479  std::string("IDL::DistinctType<") + const_str + wrapped_type_name_ +
1480  ", " + get_tag_name_i() + ">";
1481  value_access_pre_ += "(*";
1482  value_access_post_ = ".val_)" + value_access_post_;
1483  const std::string idt_arg = "(" + ref_ + ")";
1484  if (is_const_) {
1485  ref_ = wrapped_type_name_ + idt_arg;
1486  } else {
1487  ref_ = dds_generator::valid_var_name(ref_) + "_distinct_type";
1488  if (intro) {
1489  intro->insert(wrapped_type_name_ + " " + ref_ + idt_arg + ";");
1490  }
1491  }
1492  by_ref = false;
1493  }
1494 
1495  wrapped_type_name_ = const_str + wrapped_type_name_ + (by_ref ? "&" : "");
1496  done_ = true;
1497  return *this;
1498  }
1499 
1500  std::string ref() const
1501  {
1502  ACE_ASSERT(done_);
1503  return ref_;
1504  }
1505 
1506  std::string wrapped_type_name() const
1507  {
1508  ACE_ASSERT(done_);
1509  return wrapped_type_name_;
1510  }
1511 
1512  bool needs_dda_tag() const
1513  {
1514  ACE_ASSERT(done_);
1515  return needs_dda_tag_;
1516  }
1517 
1518  void generate_tag() const
1519  {
1520  if (cpp11_ || needs_dda_tag_) {
1521  be_global->header_ << "struct " << get_tag_name() << " {};\n\n";
1522  }
1523  }
1524 
1525  std::string get_tag_name() const
1526  {
1527  ACE_ASSERT(done_);
1528  return get_tag_name_i();
1529  }
1530 
1531  std::string get_var_name(const std::string& var_name) const
1532  {
1533  return var_name.size() ? var_name : to_wrap_;
1534  }
1535 
1536  std::string value_access(const std::string& var_name = "") const
1537  {
1538  return value_access_pre_ + get_var_name(var_name) + value_access_post_;
1539  }
1540 
1541  std::string seq_check_empty() const
1542  {
1543  return value_access() + (cpp11_ ? ".empty()" : ".length() == 0");
1544  }
1545 
1546  std::string seq_get_length() const
1547  {
1548  const std::string value = value_access();
1549  return cpp11_ ? "static_cast<uint32_t>(" + value + ".size())" : value + ".length()";
1550  }
1551 
1552  std::string seq_resize(const std::string& new_size) const
1553  {
1554  const std::string value = value_access();
1555  return value + (cpp11_ ? ".resize" : ".length") + "(" + new_size + ");\n";
1556  }
1557 
1558  std::string seq_get_buffer() const
1559  {
1560  return value_access() + (cpp11_ ? ".data()" : ".get_buffer()");
1561  }
1562 
1563  std::string flat_collection_access(std::string index) const
1564  {
1565  AST_Array* const array_node = dynamic_cast<AST_Array*>(type_);
1566  std::string ref;
1567  if (array_node) {
1568  ref = "(&" + value_access();
1569  for (ACE_CDR::ULong dim = array_node->n_dims(); dim; --dim) {
1570  ref += "[0]";
1571  }
1572  ref += ")";
1573  } else {
1574  ref = value_access();
1575  }
1576  return ref += "[" + index + "]";
1577  }
1578 
1579  std::string stream() const
1580  {
1581  return shift_op_ + ref();
1582  }
1583 
1584  std::string classic_array_copy() const
1585  {
1586  return type_name_ + "_copy(" + to_wrap_ + ", " + classic_array_copy_var_ + ".in());";
1587  }
1588 
1589 private:
1590  bool done_;
1591  std::string wrapped_type_name_;
1592  std::string ref_;
1593  std::string value_access_pre_;
1594  std::string value_access_post_;
1596 
1597  std::string get_tag_name_i() const
1598  {
1599  std::string qualifier;
1600  if (nested_key_only_) {
1601  qualifier = "_nested_key_only";
1602  } else if (needs_dda_tag_) {
1603  qualifier = "_dda";
1604  }
1605  return dds_generator::get_tag_name(type_name_, qualifier);
1606  }
1607 };
1608 
1609 #endif
std::string bounded_arg(AST_Type *type)
std::string to_cxx_type(AST_Type *type, std::size_t &size)
LineSet line_set
#define ACE_INT32_MIN
std::string type_to_default(const std::string &indent, AST_Type *type, const std::string &name, bool is_anonymous=false, bool is_union=false)
Classification classify(AST_Type *type)
virtual bool gen_typedef(AST_Typedef *node, UTL_ScopedName *name, AST_Type *base, const char *repoid)=0
void join(std::ostream &os, const std::string &indent)
static std::string scoped_helper(UTL_ScopedName *sn, const char *sep, EscapeContext cxt=EscapeContext_Normal)
const char * c_str(void) const
std::string field_type_name(AST_Field *field, AST_Type *field_type=0)
ACE_CDR::ULong MemberId
Definition: TypeObject.h:910
bool needs_forany(AST_Type *type)
AST_Field * value_type
std::string string_type(AstTypeClassification::Classification cls)
bool struct_has_explicit_keys(AST_Structure *node)
const LogLevel::Value value
Definition: debug.cpp:61
const Classification CL_STRING
bool extra_newline_
std::ostream & operator<<(std::ostream &o, const AST_Expression::AST_ExprValue &ev)
std::string get_tag_name() const
AST_Typedef * typedef_node_
const std::string type_name_
void output(const std::string &str) const
void insert(const std::string &line)
bool operator!=(const Iterator &other) const
Iterator begin() const
ScopedNamespaceGuard(UTL_ScopedName *name, std::ostream &os, const char *keyword="namespace")
AST_Type * deepest_named_type(AST_Type *type)
WrapDirection
const char *const shift_in
const Classification CL_SCALAR
const bool enabled_
void generateBranchLabels(AST_UnionBranch *branch, AST_Type *discriminator, size_t &n_labels, bool &has_default)
const Classification CL_WIDE
string Identifier
AST_Field *& reference
const bool explicit_keys_only_
std::string get_tag_name_i() const
virtual ~dds_generator()=0
const Classification CL_PRIMITIVE
static std::string get_xtag_name(UTL_ScopedName *name)
void generateCaseBody(CommonFn commonFn, CommonFn commonFn2, AST_UnionBranch *branch, const char *statementPrefix, const char *namePrefix, const char *uni, bool generateBreaks, bool parens)
std::string seq_get_length() const
virtual bool gen_interf_fwd(UTL_ScopedName *)
Definition: dds_generator.h:96
std::string preamble_
std::ostream & hex_value(std::ostream &o, unsigned value, size_t bytes)
Definition: ValueHelper.h:50
static std::string get_tag_name(const std::string &base_name, const std::string &qualifier="")
std::string classic_array_copy_var_
std::string seq_get_buffer() const
std::string value_access_pre_
virtual bool gen_const(UTL_ScopedName *, bool, AST_Constant *)
Definition: dds_generator.h:66
static bool explicit_keys_only(AST_Structure *node, FieldFilter filter)
bool classic_array_copy_
void extra_newline(bool value)
reference_wrapper< T > ref(T &r)
Definition: RcHandle_T.h:237
Iterator(AST_Structure *node=0, unsigned pos=0, bool explicit_keys_only=false)
std::string strip_shift_op(const std::string &s)
RefWrapper(AST_Type *type, const std::string &type_name, const std::string &to_wrap, bool is_const=true)
const Classification CL_BOUNDED
This is for everything else.
Definition: dds_generator.h:45
virtual bool gen_interf(AST_Interface *, UTL_ScopedName *, bool, const std::vector< AST_Interface *> &, const std::vector< AST_Interface *> &, const std::vector< AST_Attribute *> &, const std::vector< AST_Operation *> &, const char *)
Definition: dds_generator.h:88
std::string & indent_
#define ACE_INT64_MIN
std::string wrapped_type_name_
const std::string fieldref_
const Classification CL_ARRAY
void insert(const Intro &other)
Iterator & operator++()
#define ACE_OCTET_MAX
static bool cxx_escaped(const std::string &s)
Strip any escapes.
Definition: dds_generator.h:43
bool needSyntheticDefault(AST_Type *disc, size_t n_labels)
std::string get_var_name(const std::string &var_name) const
#define ACE_UINT16_MAX
bool generateSwitchBody(AST_Union *, 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)
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::vector< std::string > * ns_
std::string getEnumLabel(AST_Expression *label_val, AST_Type *disc)
std::string index_
ACE_CDR::ULong container_element_limit(AST_Type *type)
Christopher Diggins *renamed files *fixing compilation errors *adding Visual C project file *removed make Max Lybbert *removed references to missing and unused header
Definition: CHANGELOG.txt:8
std::string wrapped_type_name() const
virtual bool gen_enum(AST_Enum *, UTL_ScopedName *, const std::vector< AST_EnumVal *> &, const char *)
Definition: dds_generator.h:71
Iterator end() const
std::ostream & os_
static std::string to_string(Identifier *id, EscapeContext ec=EscapeContext_Normal)
Function(const std::string &name, const std::string returntype, const char *template_args=0)
Iterator operator++(int)
std::string getWrapper(const std::string &name, AST_Type *type, WrapDirection wd)
static std::string valid_var_name(const std::string &str)
AST_Type * resolveActualType(AST_Type *element)
This is for generated IDL. (Like *TypeSupport.idl)
Definition: dds_generator.h:39
const Classification CL_UNKNOWN
virtual bool do_included_files() const
Definition: dds_generator.h:60
AST_Type *const type_
Fields(AST_Structure *node=0, FieldFilter filter=FieldFilter_All)
void endArgs()
std::string classic_array_copy() const
This is for a name coming from generated IDL. (Like *TypeSupportC.h)
Definition: dds_generator.h:41
std::string insert_cxx11_accessor_parens(const std::string &full_var_name_, bool is_union_member=false)
ACE_UINT32 ULong
AST_Structure *const node_
static std::string module_scope_helper(UTL_ScopedName *sn, const char *sep, EscapeContext cxt=EscapeContext_Normal)
std::string seq_check_empty() const
std::string value_access(const std::string &var_name="") const
AST_Type * container_base_type(AST_Type *type)
bool nested_key_only_
const char *const shift_op_
bool has_arg_
const char *const name
Definition: debug.cpp:60
NamespaceGuard(bool enabled=true, std::vector< std::string > *ns=0)
virtual bool gen_union_fwd(AST_UnionFwd *, UTL_ScopedName *, AST_Type::SIZE_TYPE)
AST_Field ** pointer
AST_Structure * node() const
bool valid() const
std::string flat_collection_access(std::string index) const
const Classification CL_FIXED
RefWrapper(AST_Type *type, const std::string &type_name, const std::string &fieldref, const std::string &local, bool is_const=true)
std::string scoped(UTL_ScopedName *sn, EscapeContext ec=EscapeContext_Normal)
virtual bool gen_native(AST_Native *, UTL_ScopedName *, const char *)
Definition: dds_generator.h:99
bool needs_dda_tag_
std::string seq_resize(const std::string &new_size) const
std::vector< std::string > default_ns_
LineVec line_vec
std::string stream() const
const std::string what_
#define ACE_ASSERT(X)
const Classification CL_STRUCTURE
const std::string to_wrap_
std::set< std::string > LineSet
void addArg(const char *name, const std::string &type)
void add_generator(dds_generator *gen)
std::vector< dds_generator * > components_
BE_GlobalData * be_global
Definition: be_global.cpp:44
std::string module_scope(UTL_ScopedName *sn)
ACE_CDR::ULong array_element_count(AST_Array *arr)
std::input_iterator_tag iterator_category
std::vector< std::string > LineVec
std::string(* CommonFn)(const std::string &indent, AST_Decl *node, const std::string &name, AST_Type *type, const std::string &prefix, bool wrap_nested_key_only, Intro &intro, const std::string &)
void generate_tag() const
bool needs_dda_tag() const
std::string ref_
const char * get_shift_op(const std::string &s)
const Classification CL_INTERFACE
RefWrapper & done(Intro *intro=0)
std::ostream & os_
EscapeContext
Definition: dds_generator.h:37
bool dynamic_data_adapter_
const std::string indent_
std::string ref() const
void misc_error_and_abort(const std::string &message, AST_Decl *node=0)
Report a miscellaneous error and abort.
virtual bool gen_struct_fwd(UTL_ScopedName *, AST_Type::SIZE_TYPE)
Definition: dds_generator.h:81
virtual bool gen_union(AST_Union *node, UTL_ScopedName *name, const std::vector< AST_UnionBranch *> &branches, AST_Type *discriminator, const char *repoid)=0
unsigned pos() const
Iterator operator[](unsigned position) const
int insert(Container &c, const ValueType &v)
Definition: Util.h:105
AST_Field * operator*() const
const std::string local_
virtual bool gen_struct(AST_Structure *node, UTL_ScopedName *name, const std::vector< AST_Field *> &fields, AST_Type::SIZE_TYPE size, const char *repoid)=0
AST_Structure * node_
const bool cpp11_
virtual void gen_prologue()
Definition: dds_generator.h:62
std::string value_access_post_
const Classification CL_ENUM
const char *const shift_out
const Classification CL_SEQUENCE
bool operator==(const Iterator &other) const
composite_generator(InputIterator begin, InputIterator end)
PreprocessorIfGuard(const std::string &what, bool impl=true, bool header=true, const std::string &indent="")
FieldFilter
#define ACE_UINT32_MAX
std::string wrapPrefix(AST_Type *type, WrapDirection wd)
bool needs_distinct_type(AST_Type *type)
bool needs_nested_key_only(AST_Type *type)
const Classification CL_UNION
AST_Field * get_struct_field(AST_Structure *struct_node, unsigned index)
virtual void gen_epilogue()
Definition: dds_generator.h:64