RefleX
Build DDS Applications in Modern C++ without IDL
 All Classes Namespaces Files Functions Variables Typedefs Enumerator Friends Macros Pages
typecode_manip.h
Go to the documentation of this file.
1 /*********************************************************************************************
2 (c) 2005-2014 Copyright, Real-Time Innovations, Inc. All rights reserved.
3 RTI grants Licensee a license to use, modify, compile, and create derivative works
4 of the Software. Licensee has the right to distribute object form only for use with RTI
5 products. The Software is provided "as is", with no warranty of any type, including
6 any warranty for fitness for any purpose. RTI is under no obligation to maintain or
7 support the Software. RTI shall not be liable for any incidental or consequential
8 damages arising out of the use or inability to use the software.
9 **********************************************************************************************/
10 
11 #ifndef RTIREFLEX_TYPECODE_MANIP_H
12 #define RTIREFLEX_TYPECODE_MANIP_H
13 
14 #include <iostream>
15 #include <string>
16 #include <vector>
17 
18 #include <ndds/ndds_cpp.h>
19 #include "reflex/safe_typecode.h"
20 #include "reflex/member_names.h"
21 #include "reflex/enable_if.h"
22 #include "reflex/disc_union.h"
23 #include "reflex/tuple_iterator.h"
24 #include "reflex/bounded.h"
25 #include "reflex/dllexport.h"
26 #include "reflex/reflex_fwd.h"
27 
28 #define GET_PRIMITIVE_TC_DEF(BASIC_TYPE, TYPECODE) \
29 static const DDS_TypeCode * \
30  get_primitive_tc(DDS_TypeCodeFactory * factory, \
31  const BASIC_TYPE *) { \
32  return factory->get_primitive_tc(TYPECODE); \
33 }
34 
35 namespace reflex {
36 
37  namespace detail {
38 
40  print_IDL(
41  const DDS_TypeCode * tc,
42  DDS_UnsignedLong indent);
43 
44  template <size_t I, class DimList>
45  struct CopyDims;
46 
47  template <size_t I, size_t Head, size_t... Tail>
48  struct CopyDims <I, reflex::meta::dim_list<Head, Tail...>>
49  {
50  static void exec(DDS_UnsignedLongSeq & seq)
51  {
52  seq[I] = Head;
53  detail::CopyDims<I + 1, reflex::meta::dim_list<Tail...>>::exec(seq);
54  }
55  };
56 
57  template <size_t I, size_t Last>
58  struct CopyDims<I, reflex::meta::dim_list<Last>>
59  {
60  static void exec(DDS_UnsignedLongSeq & seq)
61  {
62  seq[I] = Last;
63  }
64  };
65 
66  template <class Tuple, size_t I, size_t MAX_INDEX, class Case>
67  struct MatchDefaultCase;
68 
69  template <class Tuple, size_t I, size_t MAX_INDEX, class T, int Tag, int... Tags>
70  struct MatchDefaultCase<Tuple, I, MAX_INDEX, match::Case<T, Tag, Tags...>>
71  {
72  enum {
73  value =
74  detail::MatchDefaultCase<Tuple,
75  I + 1,
76  MAX_INDEX,
77  typename std::tuple_element<I + 1, Tuple>::type
78  >::value
79  };
80  };
81 
82  template <class Tuple, size_t MAX_INDEX, class T, int Tag, int... Tags>
83  struct MatchDefaultCase<Tuple, MAX_INDEX, MAX_INDEX, match::Case<T, Tag, Tags...>>
84  {
85  enum { value = -1 };
86  };
87 
88  template <class Tuple, size_t I, size_t MAX_INDEX, class T>
89  struct MatchDefaultCase<Tuple, I, MAX_INDEX, match::Case<T>>
90  {
91  enum { value = I };
92  };
93 
94  template <class Tuple, size_t MAX_INDEX, class T>
95  struct MatchDefaultCase<Tuple, MAX_INDEX, MAX_INDEX, match::Case<T>>
96  {
97  enum { value = MAX_INDEX };
98  };
99 
100  template <class TagType, class... Cases>
101  struct DefaultCaseIndex;
102 
103  template <class TagType, class... Cases>
104  struct DefaultCaseIndex<match::Union<TagType, Cases...>>
105  {
106  typedef typename match::Union<TagType, Cases...>::case_tuple_type CaseTuple;
107  enum {
108  value =
109  MatchDefaultCase<CaseTuple,
110  1,
112  typename std::tuple_element<1, CaseTuple>::type>::value
113  };
114  };
115 
116  struct Primitive_TC_Helper
117  {
118  GET_PRIMITIVE_TC_DEF(match::octet_t, DDS_TK_OCTET)
119  GET_PRIMITIVE_TC_DEF(bool, DDS_TK_BOOLEAN)
120  GET_PRIMITIVE_TC_DEF(char, DDS_TK_CHAR)
121  GET_PRIMITIVE_TC_DEF(int8_t, DDS_TK_CHAR)
122  GET_PRIMITIVE_TC_DEF(int16_t, DDS_TK_SHORT)
123  GET_PRIMITIVE_TC_DEF(uint16_t, DDS_TK_USHORT)
124  GET_PRIMITIVE_TC_DEF(int32_t, DDS_TK_LONG)
125  GET_PRIMITIVE_TC_DEF(uint32_t, DDS_TK_ULONG)
126  GET_PRIMITIVE_TC_DEF(int64_t, DDS_TK_LONGLONG)
127  GET_PRIMITIVE_TC_DEF(uint64_t, DDS_TK_ULONGLONG)
128  GET_PRIMITIVE_TC_DEF(float, DDS_TK_FLOAT)
129  GET_PRIMITIVE_TC_DEF(double, DDS_TK_DOUBLE)
130  GET_PRIMITIVE_TC_DEF(long double, DDS_TK_LONGDOUBLE)
131 
132 #ifndef RTI_WIN32
133  GET_PRIMITIVE_TC_DEF(char32_t, DDS_TK_WCHAR)
134 #endif
135 
136 #if __x86_64__
137  GET_PRIMITIVE_TC_DEF(long long, DDS_TK_LONGLONG)
138  GET_PRIMITIVE_TC_DEF(unsigned long long, DDS_TK_ULONGLONG)
139 #endif
140  };
141 
142  template <class T>
143  struct Enum_TC_Helper
144  {
145  template <size_t I, size_t MAX>
146  struct SetEnumMembers
147  {
148  static void exec(DDS_EnumMemberSeq & enum_seq,
149  std::vector<reflex::codegen::MemberInfo> & info_seq)
150  {
151  using namespace detail;
153 
154  info_seq[I] = EnumDef<T>::template EnumMember<I>::info();
155  enum_seq[I].name = const_cast<char *>(info_seq[I].name.c_str());
156  enum_seq[I].ordinal = info_seq[I].value;
157  SetEnumMembers<I + 1, MAX>::exec(enum_seq, info_seq);
158  }
159  };
160 
161  template <size_t MAX>
162  struct SetEnumMembers<MAX, MAX>
163  {
164  static void exec(DDS_EnumMemberSeq & enum_seq,
165  std::vector<reflex::codegen::MemberInfo> & info_seq)
166  {
167  using namespace detail;
169 
170  info_seq[MAX] = EnumDef<T>::template EnumMember<MAX>::info();
171  enum_seq[MAX].name = const_cast<char *>(info_seq[MAX].name.c_str());
172  enum_seq[MAX].ordinal = info_seq[MAX].value;
173  }
174  };
175 
176  };
177 
178  struct Struct_TC_Helper
179  {
180  template <class T>
181  static SafeTypeCode<T> get_typecode_struct(
182  const char * name,
183  reflex::meta::false_type /* T has no base */)
184  {
185  DDS_TypeCodeFactory * factory =
186  DDS_TypeCodeFactory::get_instance();
187 
188  std::string struct_name =
190 
191  const char * type_name =
192  name ? name : struct_name.c_str();
193 
194  //SafeTypeCode<T> structTc(factory, type_name);
195  DDS_ExceptionCode_t ex;
196  DDS_TypeCode *structTc =
197  factory->create_struct_tc(type_name,
198  DDS_StructMemberSeq(), ex);
199 
200  SafeTypeCode<T> safetc(factory, structTc);
201 
202  check_exception_code(
203  "get_typecode_struct: Unable to create struct typecode, error = ",
204  ex);
205 
206  detail::TypelistIterator<
207  T,
208  0,
210  factory, safetc.get());
211 
212  return safetc;
213  }
214 
215  template <class T>
216  static SafeTypeCode<T> get_typecode_struct(
217  const char * name,
218  reflex::meta::true_type /* T has base */)
219  {
220  DDS_TypeCodeFactory * factory =
221  DDS_TypeCodeFactory::get_instance();
222 
223  std::string struct_name =
225 
226  const char * type_name =
227  name ? name : struct_name.c_str();
228 
230 
231  SafeTypeCode<BaseType> baseTc =
232  get_typecode_struct<BaseType>(
233  0,
235 
236  DDS_ExceptionCode_t ex;
237  DDS_TypeCode *valueTc =
238  factory->create_value_tc(
239  type_name,
240  DDS_EXTENSIBLE_EXTENSIBILITY,
241  DDS_VM_NONE,
242  baseTc.get(),
243  DDS_ValueMemberSeq(),
244  ex);
245 
246  SafeTypeCode<T> aggregateTc(factory, valueTc);
247 
248  check_exception_code(
249  "get_typecode_struct: Unable to create valuetype typecode, error = ",
250  ex);
251 
252  detail::TypelistIterator<
253  T,
254  0,
256  ::add(factory, aggregateTc.get());
257 
258  return aggregateTc;
259  }
260  };
261 
262  /* TypeCode Overload Resolution Helper */
263  /* Overload resolution of several free primary template
264  * functions can be notoriously brittle due to
265  * ordering issues. In general, a function must be declared
266  * before it is called. Sounds simple but in a set of mutually
267  * recursive primary template functions, it is easy to lose
268  * grip on the what's declared before and what's not. In
269  * general, all the functions should be declared beforehand.
270  * There is an alternative solution that is used here.
271  * Put all the functions in a class and make them static
272  * and use their fully qualified name to call them.
273  * No upfront declarations are necessary if this idiom is used.
274  * */
275  struct TC_Helper
276  {
277  template <class Str>
278  static SafeTypeCode<Str>
279  get_typecode(
280  DDS_TypeCodeFactory * factory,
281  const Str *,
283  {
284  DDS_ExceptionCode_t ex;
285 
286  SafeTypeCode<Str> stringTc(
287  factory,
288  factory->create_string_tc(reflex::type_traits::static_string_bound<Str>::value,
289  ex));
290 
291  check_exception_code(
292  "InnerTypeCodeBase::create_string_tc: Unable to create string typecode, error = ",
293  ex);
294 
295  return stringTc;
296  }
297 
298  template <class T>
299  // overload for
300  // 1. user-defined structs adapted as a Fusion Sequence
301  // 2. tuples.
302  static SafeTypeCode<T> get_typecode(
303  DDS_TypeCodeFactory * factory,
304  const T *,
311  {
312  return Struct_TC_Helper::get_typecode_struct<T>(
313  0 /* name */,
315  }
316 
317  template <class T>
318  // overload for all the primitive types.
319  static SafeTypeCode<T> get_typecode(
320  DDS_TypeCodeFactory * factory,
321  const T * primitive,
323  {
324  return SafeTypeCode<T>(factory,
325  Primitive_TC_Helper::get_primitive_tc(factory, primitive));
326  }
327 
328  template <class T>
329  // overload for user-defined enumeration types.
330  static SafeTypeCode<T> get_typecode(
331  DDS_TypeCodeFactory * factory,
332  const T *,
334  {
335  // The lifetime of info_seq must be until create_enum_tc is invoked
336  // because enum_seq[i].name is just a pointer to MemberInfo.name strings
338 
339  DDS_ExceptionCode_t ex;
340  DDS_EnumMemberSeq enum_seq;
341  std::vector<reflex::codegen::MemberInfo> info_seq(EnumDef<T>::size);
342  enum_seq.ensure_length(EnumDef<T>::size, EnumDef<T>::size);
343  Enum_TC_Helper<T>::template SetEnumMembers<0, EnumDef<T>::size - 1>::exec(enum_seq, info_seq);
344 
345  SafeTypeCode<T> enumTc(
346  factory,
347  factory->create_enum_tc(EnumDef<T>::name(), enum_seq, ex));
348 
349  check_exception_code(
350  "get_typecode: Unable to create enum typecode, error = ",
351  ex);
352 
353  return enumTc;
354  }
355 
356  template <class C, size_t Bound>
357  static SafeTypeCode<reflex::match::Bounded<C, Bound>> get_typecode(
358  DDS_TypeCodeFactory * factory,
361  {
362  SafeTypeCode<typename C::value_type> innerTc
363  = TC_Helper::get_typecode(
364  factory,
365  static_cast<typename C::value_type *>(0));
366 
367  DDS_ExceptionCode_t ex;
368  SafeTypeCode<reflex::match::Bounded<C, Bound>> seqTc
369  (factory,
370  factory->create_sequence_tc(Bound, innerTc.get(), ex));
371 
372  check_exception_code(
373  "get_typecode: Unable to create sequence typecode, error = ",
374  ex);
375 
376  return seqTc;
377  }
378 
379  template <class C>
380  static SafeTypeCode<C> get_typecode(
381  DDS_TypeCodeFactory * factory,
382  const C *,
384  {
385  SafeTypeCode<typename reflex::type_traits::container_traits<C>::value_type> innerTc
386  = TC_Helper::get_typecode(
387  factory,
388  static_cast<typename reflex::type_traits::container_traits<C>::value_type *>(0));
389 
390  DDS_ExceptionCode_t ex;
391  SafeTypeCode<C> seqTc(
392  factory,
393  factory->create_sequence_tc(reflex::type_traits::static_container_bound<C>::value,
394  innerTc.get(),
395  ex));
396 
397  check_exception_code(
398  "get_typecode: Unable to create sequence typecode, error = ",
399  ex);
400 
401  return seqTc;
402  }
403 
404  template <class T, size_t N>
405  static SafeTypeCode<std::array<T, N>> get_typecode(
406  DDS_TypeCodeFactory * factory,
407  const std::array<T, N> *)
408  {
409  typedef typename reflex::meta::remove_all_extents<T>::type BasicType;
410  SafeTypeCode<BasicType> basicTc
411  = TC_Helper::get_typecode(
412  factory,
413  static_cast<BasicType *>(0));
414 
415  DDS_UnsignedLongSeq dims;
416  typedef typename
418  dims.ensure_length(DimList::size, DimList::size);
419  detail::CopyDims<0, DimList>::exec(dims);
420 
421  DDS_ExceptionCode_t ex;
422  SafeTypeCode<std::array<T, N>> arrayTc(
423  factory,
424  factory->create_array_tc(dims, basicTc.get(), ex));
425 
426  check_exception_code(
427  "InnerTypeCodeBase::create_array_tc: Unable to create array typecode, error = ",
428  ex);
429 
430  return arrayTc;
431  }
432 
433  template <size_t Bound>
434  static SafeTypeCode<reflex::match::Bounded<std::string, Bound>>
435  get_typecode(
436  DDS_TypeCodeFactory * factory,
438  {
439  DDS_ExceptionCode_t ex;
440 
441  SafeTypeCode<match::Bounded<std::string, Bound>>
442  stringTc(factory, factory->create_string_tc(Bound, ex));
443 
444  check_exception_code(
445  "get_typecode::create_string_tc: Unable to create string typecode, error = ",
446  ex);
447 
448  return stringTc;
449  }
450 
451  template <class T>
452  static SafeTypeCode<match::Range<T>> get_typecode(
453  DDS_TypeCodeFactory * factory,
454  const reflex::match::Range<T> *)
455  {
456  SafeTypeCode<typename reflex::meta::remove_reference<T>::type> innerTc
457  = TC_Helper::get_typecode(
458  factory,
459  static_cast<typename reflex::meta::remove_reference<T>::type *>(0));
460 
461  DDS_ExceptionCode_t ex;
462  SafeTypeCode<match::Range<T>> seqTc(
463  factory,
464  factory->create_sequence_tc(
465  reflex::type_traits::static_container_bound<match::Range<T>>::value,
466  innerTc.get(),
467  ex));
468 
469  check_exception_code(
470  "get_typecode: Unable to create sequence typecode, error = ",
471  ex);
472 
473  return seqTc;
474  }
475 
476 /*
477 #ifdef RTI_WIN32
478 
479  template <class... T>
480  static SafeTypeCode<boost::optional<T...>> get_typecode(
481  DDS_TypeCodeFactory * factory,
482  const boost::optional<T...> *)
483  {
484  typedef typename packhead<T...>::type HeadT;
485  SafeTypeCode<HeadT> innerTc =
486  TC_Helper::get_typecode(
487  factory,
488  static_cast<HeadT *>(0));
489 
490  return SafeTypeCode<boost::optional<T...>>(factory, move(innerTc));
491  }
492 #else
493  template <class T>
494  static SafeTypeCode<boost::optional<T>> get_typecode(
495  DDS_TypeCodeFactory * factory,
496  const boost::optional<T> *)
497  {
498  SafeTypeCode<T> innerTc =
499  TC_Helper::get_typecode(
500  factory,
501  static_cast<T *>(0));
502 
503  return SafeTypeCode<boost::optional<T>>(factory, move(innerTc));
504  }
505 #endif
506 */
507 
508  template <class Opt>
509  static SafeTypeCode<Opt> get_typecode(
510  DDS_TypeCodeFactory * factory,
511  const Opt * opt,
513  {
514  typedef
517  decltype(**opt)
518  >::type
519  >::type
520  OptValuetype;
521 
522  SafeTypeCode<OptValuetype> innerTc =
523  TC_Helper::get_typecode(
524  factory,
525  static_cast<OptValuetype *>(0));
526 
527  DDS_ExceptionCode_t ex = DDS_NO_EXCEPTION_CODE;
528  SafeTypeCode<Opt> optionalTc(
529  factory,
530  factory->clone_tc(innerTc.get(), ex));
531 
532  check_exception_code(
533  "get_typecode<optional>: Unable to clone typecode, error = ",
534  ex);
535 
536  return optionalTc;
537  }
538 
539  template <class T, size_t Bound>
540  static SafeTypeCode<match::BoundedRange<T, Bound>> get_typecode(
541  DDS_TypeCodeFactory * factory,
543  {
544  SafeTypeCode<typename reflex::meta::remove_reference<T>::type> innerTc
545  = TC_Helper::get_typecode(
546  factory,
547  static_cast<typename reflex::meta::remove_reference<T>::type *>(0));
548 
549  DDS_ExceptionCode_t ex = DDS_NO_EXCEPTION_CODE;
550  SafeTypeCode<match::BoundedRange<T, Bound>> seqTc(
551  factory,
552  factory->create_sequence_tc(Bound, innerTc.get(), ex));
553 
554  check_exception_code(
555  "get_typecode<BoundedRange>: Unable to create sequence typecode, error = ",
556  ex);
557 
558  return seqTc;
559  }
560 
561  template <class... Args>
562  static SafeTypeCode<reflex::match::Sparse<Args...>> get_typecode(
563  DDS_TypeCodeFactory * factory,
565  {
566  DDS_ExceptionCode_t ex = DDS_NO_EXCEPTION_CODE;
567  SafeTypeCode<reflex::match::Sparse<Args...>> sparseTc(
568  factory,
569  factory->create_sparse_tc(reflex::codegen::StructName<reflex::match::Sparse<Args...>>::get().c_str(),
570  DDS_VM_NONE,
571  NULL,
572  ex));
573 
574  check_exception_code(
575  "get_typecode<Sparse>: Unable to create sparse typecode, error = ",
576  ex);
577 
578  typedef typename
579  ::reflex::match::Sparse<Args...>::raw_tuple_type RawTuple;
580 
581  TypelistIterator<RawTuple,
582  0,
584  factory, sparseTc.get());
585 
586  return sparseTc;
587  }
588 
589  template <class TagType, class... Cases>
590  static SafeTypeCode<reflex::match::Union<TagType, Cases...>>
591  get_typecode(
592  DDS_TypeCodeFactory * factory,
594  {
595  SafeTypeCode<TagType> discTc =
596  TC_Helper::get_typecode(
597  factory,
598  static_cast<TagType *>(0));
599 
600  typedef typename
601  reflex::match::Union<TagType, Cases...>::case_tuple_type CaseTuple;
602 
603  DDS_UnionMemberSeq umember_seq;
604  const size_t ncases = reflex::meta::size<CaseTuple>::value;
605  umember_seq.ensure_length(ncases, ncases);
606 
607  TC_Helper::add_union_members(
608  factory,
609  umember_seq,
610  static_cast<reflex::match::Union<TagType, Cases...> *>(0));
611 
612  DDS_ExceptionCode_t ex = DDS_NO_EXCEPTION_CODE;
613  SafeTypeCode<reflex::match::Union<TagType, Cases...>> unionTc(
614  factory,
615  factory->create_union_tc(reflex::codegen::StructName<reflex::match::Union<TagType, Cases...>>::get().c_str(),
616  discTc.get(),
617  detail::DefaultCaseIndex<match::Union<TagType, Cases...>>::value,
618  umember_seq,
619  ex));
620 
621  check_exception_code(
622  "get_typecode<Union>: Unable to create union typecode, error = ",
623  ex);
624 
625  TypelistIterator<CaseTuple,
626  0,
627  reflex::meta::size<CaseTuple>::value - 1>::delete_typecodes(factory, umember_seq);
628 
629  return unionTc;
630  }
631 
632  template<class T>
633  static SafeTypeCode<T> get_typecode(
634  DDS_TypeCodeFactory * factory,
635  T *,
637  {
638  typedef typename reflex::meta::remove_all_extents<T>::type InnerType;
639 
640  SafeTypeCode<InnerType> innerTc =
641  TC_Helper::get_typecode(
642  factory,
643  static_cast<InnerType *>(0));
644 
645  typedef typename reflex::meta::make_dim_list<T>::type DimList;
646 
647  DDS_UnsignedLongSeq dims;
648  dims.ensure_length(DimList::size, DimList::size);
649  detail::CopyDims<0, DimList>::exec(dims);
650 
651  DDS_ExceptionCode_t ex = DDS_NO_EXCEPTION_CODE;
652  SafeTypeCode<T> arrayTc(
653  factory,
654  factory->create_array_tc(dims, innerTc.get(), ex));
655 
656  check_exception_code(
657  "add_member_impl<BuiltInArray>: Unable to create array typecode, error = ",
658  ex);
659 
660  return arrayTc;
661  }
662 
663  private:
664 
665  template <class TagType, class... Cases>
666  static void add_union_members(
667  DDS_TypeCodeFactory * factory,
668  DDS_UnionMemberSeq & seq,
670  {
671  typedef typename
672  reflex::match::Union<TagType, Cases...>::case_tuple_type CaseTuple;
673  TypelistIterator<CaseTuple,
674  0,
675  reflex::meta::size<CaseTuple>::value - 1>::add_union_member(factory, seq);
676  }
677 
678  }; // struct TC_Helper
679 
680  template <class T>
681  void add_member_impl(
682  DDS_TypeCodeFactory * factory,
683  DDS_TypeCode * outerTc,
684  const char * member_name,
685  unsigned char flags,
686  int id,
687  T *)//,
688  //typename reflex::meta::disable_if<reflex::type_traits::is_builtin_array<T>::value>::type * = 0)
689  {
690  DDS_ExceptionCode_t ex;
691  SafeTypeCode<T> innerTc =
692  TC_Helper::get_typecode(
693  factory,
694  static_cast<T *>(0));
695 
696  DDS_Long member_id =
697  (outerTc->kind(ex) == DDS_TK_SPARSE) ? id : DDS_TYPECODE_MEMBER_ID_INVALID;
698 
699  outerTc->add_member(member_name,
700  member_id,
701  innerTc.get(),
702  flags,
703  ex);
704 
705  detail::check_exception_code(
706  "add_member_impl<T>: Unable to add inner typecode, error = ",
707  ex);
708  }
709  /*
710  template <class T>
711  void add_member_impl(
712  DDS_TypeCodeFactory * factory,
713  DDS_TypeCode * outerTc,
714  const char * member_name,
715  unsigned char flags,
716  int id,
717  const T *,
718  typename reflex::meta::enable_if<reflex::type_traits::is_builtin_array<T>::value>::type * = 0)
719  {
720  // Simple overloading is not used to get typecode for built-in
721  // arrays because square brackets must be expanded syntactically.
722  // I.e., For N-dimensional array you have to write a template of N
723  // integral parameters because there is no way to say [0...N]. Sigh!
724  typedef typename reflex::meta::remove_all_extents<T>::type InnerType;
725 
726  SafeTypeCode<InnerType> innerTc =
727  TC_Helper::get_typecode(
728  factory,
729  static_cast<InnerType *>(0));
730 
731  typedef typename reflex::meta::make_dim_list<T>::type DimList;
732 
733  DDS_UnsignedLongSeq dims;
734  dims.ensure_length(DimList::size, DimList::size);
735  detail::CopyDims<0, DimList::exec(dims);
736 
737  DDS_ExceptionCode_t ex = DDS_NO_EXCEPTION_CODE;
738  SafeTypeCode<T> arrayTc(
739  factory,
740  factory->create_array_tc(dims, innerTc.get(), ex);
741 
742  check_exception_code(
743  "add_member_impl<BuiltInArray>: Unable to create array typecode, error = ",
744  ex);
745 
746  DDS_ExceptionCode_t ex = DDS_NO_EXCEPTION_CODE;
747  outerTc->add_member(member_name,
748  DDS_TYPECODE_MEMBER_ID_INVALID,
749  arrayTc.get(),
750  flags,
751  ex);
752 
753  detail::check_exception_code(
754  "add_member_impl<BuiltInArray>: Unable to add inner array typecode, error = ",
755  ex);
756  }
757  */
758  template <class T>
759  void add_member_forward(
760  DDS_TypeCodeFactory * factory,
761  DDS_TypeCode * outerTc,
762  const char * member_name,
763  unsigned char flags,
764  int id,
765  const T * tptr)
766  {
768  {
769  if (flags == DDS_TYPECODE_KEY_MEMBER)
770  {
771  std::stringstream stream;
772  stream << "add_member_forward: optinal member "
773  << member_name
774  << " can't be a key.";
775  throw std::runtime_error(stream.str());
776  }
777  else
778  flags = DDS_TYPECODE_NONKEY_MEMBER;
779  }
780 
781  add_member_impl(
782  factory,
783  outerTc,
784  member_name,
785  flags,
786  id,
787  const_cast<T *>(tptr));
788  }
789 
790  template <size_t I, class Case>
791  struct LabelAdder;
792 
793  template <size_t I, class T, int Head, int... Tail>
794  struct LabelAdder<I, match::Case<T, Head, Tail...>>
795  {
796  enum { count = 1 + sizeof...(Tail) };
797 
798  static void exec(DDS_LongSeq & seq)
799  {
800  seq[I] = Head;
801  LabelAdder<I + 1, match::Case<T, Tail...>>::exec(seq);
802  }
803  };
804 
805  template <size_t I, class T, int Last>
806  struct LabelAdder<I, match::Case<T, Last>>
807  {
808  enum { count = 1 };
809 
810  static void exec(DDS_LongSeq & seq)
811  {
812  seq[I] = Last;
813  }
814  };
815 
816  template <size_t I, class T>
817  struct LabelAdder<I, match::Case<T>>
818  {
819  enum { count = 1 };
820 
821  static void exec(DDS_LongSeq & seq)
822  {
823  seq[I] = -1; // default member
824  }
825  };
826 
827 
828  template <class Case>
829  void case_add_impl(
830  DDS_TypeCodeFactory * factory,
831  const char * member_name,
832  DDS_UnionMember & umember)//,
833  //typename reflex::meta::disable_if<
834  // reflex::type_traits::is_builtin_array<typename Case::type
835  // >::value>::type * = 0)
836  {
837  DDS_LongSeq label_seq;
838  label_seq.ensure_length(
839  LabelAdder<0, Case>::count,
840  LabelAdder<0, Case>::count);
841  LabelAdder<0, Case>::exec(label_seq);
842 
843  umember.name = const_cast<char *>(member_name);
844  umember.is_pointer =
846 
847  typedef typename reflex::meta::remove_reference<typename Case::type>::type CaseTypeNoRef;
848  // typecodes are deleted in get_typecode() overload for Union.
849  umember.type =
850  TC_Helper::get_typecode(
851  factory,
852  static_cast<CaseTypeNoRef *>(0)).release();
853 
854  umember.labels = label_seq;
855  };
856  /*
857  template <class Case>
858  void case_add_impl(
859  DDS_TypeCodeFactory * factory,
860  const char * member_name,
861  DDS_UnionMember & umember,
862  typename reflex::meta::enable_if<
863  reflex::type_traits::is_builtin_array<typename Case::type>::value
864  >::type * = 0)
865  {
866  DDS_LongSeq label_seq;
867  label_seq.ensure_length(
868  LabelAdder<0, Case>::count,
869  LabelAdder<0, Case>::count);
870  LabelAdder<0, Case>::exec(label_seq);
871 
872  umember.name = const_cast<char *>(member_name);
873  umember.is_pointer =
874  reflex::type_traits::is_pointer<typename Case::type>::value;
875 
876  // typecodes is deleted in get_typecode() overload for Union.
877  typedef typename
878  reflex::meta::remove_all_extents<typename Case::type>::type BasicType;
879 
880  SafeTypeCode<BasicType> basicTc =
881  TC_Helper::get_typecode(
882  factory,
883  static_cast<BasicType *>(0));
884 
885  SafeTypeCode<BasicType,
886  typename reflex::meta::make_dim_list<typename Case::type>::type>
887  arrayTc(factory, basicTc);
888 
889  umember.type = arrayTc.release();
890 
891  umember.labels = label_seq;
892  };
893  */
894  template <class Case>
895  void case_add_forward(
896  DDS_TypeCodeFactory * factory,
897  const char * member_name,
898  DDS_UnionMember & umember)
899  {
900  case_add_impl<Case>(factory, member_name, umember);
901  }
902 
903  template <class T>
904  void deleteTc_impl(
905  DDS_TypeCodeFactory * factory,
906  DDS_TypeCode * tc,
908  {
909  // No-op
910  }
911 
912  template <class T>
913  void deleteTc_impl(
914  DDS_TypeCodeFactory * factory,
915  DDS_TypeCode * tc,
917  {
918  DDS_ExceptionCode_t ex;
919  factory->delete_tc(tc, ex);
920 
921  if (ex != DDS_NO_EXCEPTION_CODE)
922  {
923  std::cerr << "deleteTc: Unable to delete typecode, error = "
924  << detail::get_readable_ex_code(ex)
925  << std::endl;
926  // do not throw
927  }
928  }
929 
930  template <class TC>
931  void deleteTc_forward(
932  DDS_TypeCodeFactory * factory,
933  DDS_TypeCode * tc)
934  {
935  deleteTc_impl<TC>(factory, tc);
936  }
937 
938  } // namespace detail
939 
940 } // namespace reflex
941 
942 #ifndef REFLEX_NO_HEADER_ONLY
943  #include "reflex/../../src/typecode_manip.cxx"
944 #endif
945 
946 #endif // RTIREFLEX_TYPECODE_MANIP_H
947 
Definition: enable_if.h:413
Definition: disc_union.h:139
T type
Definition: enable_if.h:591
Definition: disc_union.h:27
Definition: enable_if.h:329
#define REFLEX_DECLSPEC
Definition: dllexport.h:36
Definition: enable_if.h:115
boost::any_range< T, boost::forward_traversal_tag, T, std::ptrdiff_t > Range
Definition: enable_if.h:95
Definition: enable_if.h:679
Definition: enable_if.h:502
Definition: enable_if.h:580
disable_if_lazy< reflex::type_traits::is_tuple< FusionSeq >::value, at< FusionSeq, I > >::type get(FusionSeq &seq)
Definition: enable_if.h:714
Definition: enable_if.h:132
#define GET_PRIMITIVE_TC_DEF(BASIC_TYPE, TYPECODE)
Definition: typecode_manip.h:28
Definition: enable_if.h:344
#define REFLEX_DLL_EXPORT
Definition: dllexport.h:35
Definition: enable_if.h:284
Definition: bounded.h:24
Definition: member_names.h:99
Definition: enable_if.h:251
Definition: enable_if.h:493
Definition: enable_if.h:536
Definition: enable_if.h:215
T type
Definition: enable_if.h:571
Definition: enable_if.h:353
Definition: enable_if.h:466
unsigned char octet_t
Definition: dd_extra.h:48
reflex::meta::false_type has_base
Definition: enable_if.h:467
container_traits_impl< C, is_container< C >::value >::value_type value_type
Definition: enable_if.h:447
Definition: enable_if.h:473
Definition: enable_if.h:570
Definition: bounded.h:21
Definition: enable_if.h:518
Definition: enable_if.h:119
Definition: enable_if.h:302