RTI Connext Traditional C++ API  Version 6.0.1
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
Offset.hpp
1 /*
2 (c) Copyright, Real-Time Innovations, 2018.
3 All rights reserved.
4 
5 No duplications, whole or partial, manual or electronic, may be made
6 without express written permission. Any such copies, or
7 revisions thereof, must display this notice unaltered.
8 This code contains trade secrets of Real-Time Innovations, Inc.
9 */
10 
11 #ifndef RTI_DDS_FLAT_FLATOFFSETS_HPP_
12 #define RTI_DDS_FLAT_FLATOFFSETS_HPP_
13 
14 #include "xcdr/xcdr_stream.h"
15 #include "xcdr/xcdr_stream_impl.h"
16 #include "xcdr/xcdr_interpreter.h"
17 
18 #include "rti/xcdr/Stream.hpp"
19 
108 #ifdef DOXYGEN_DOCUMENTATION_ONLY
109 
125 class MyFlatFinalOffset : public rti::flat::FinalOffset<MyFlatFinalOffset> {
126  public:
135  typedef MyFlatFinalConstOffset ConstOffset;
136 
143  {
144  }
145 
149  int32_t my_primitive() const;
150 
156  FlatFinalBar::ConstOffset my_complex() const;
157 
162 
167 
171  bool my_primitive(int32_t value);
172 
178  FlatFinalBar::Offset my_complex();
179 
184 
189 };
190 
203 class NDDSUSERDllExport MyFlatMutableOffset : public rti::flat::MutableOffset {
204  public:
213  typedef MyFlatMutableConstOffset ConstOffset;
214 
221  {
222  }
223 
230  int32_t my_primitive() const;
231 
240  rti::flat::PrimitiveConstOffset<int32_t> my_optional_primitive() const;
241 
245  const rti::flat::PrimitiveArrayOffset<int32_t, 10> my_primitive_array() const;
246 
250  const rti::flat::PrimitiveSequenceOffset<int32_t> my_primitive_seq() const;
251 
255  MyFlatFinal::ConstOffset my_final() const;
256 
261 
266 
272  FlatMutableBar::ConstOffset my_mutable() const;
273 
278 
283 
287  const rti::flat::StringOffset my_string() const;
288 
293 
297  bool my_primitive(int32_t value);
298 
299  /* @brief Retrieves a non-const Offset to an optional primitive
300  *
301  * Unlike the non-optional my_primitive(), which allows accessing the integer
302  * directly, an optional primitive may not exist. If it doesn't, the Offset
303  * this function returns will be null (\p is_null()).
304  */
305  rti::flat::PrimitiveOffset<int32_t> my_optional_primitive();
306 
310  rti::flat::PrimitiveArrayOffset<int32_t, 10> my_primitive_array();
311 
316 
320  MyFlatFinal::Offset my_final();
321 
326 
331 
337  FlatMutableBar::Offset my_mutable();
338 
343 
348 
352  rti::flat::StringOffset my_string();
353 
358 };
359 
375 class NDDSUSERDllExport MyFlatUnionOffset
376 : public rti::flat::MutableOffset {
377  public:
381  typedef MyFlatUnionConstOffset ConstOffset;
382 
389  {
390  }
391 
411  int32_t _d() const;
412 
419  int32_t my_primitive() const;
420 
427  MyFlatMutable::ConstOffset my_mutable() const;
428 
435  MyFlatFinal::ConstOffset my_final() const;
436 
445  bool my_primitive(int32_t value);
446 
453  MyFlatMutable::Offset my_mutable();
454 
461  MyFlatFinal::Offset my_final();
462 };
463 
464 #endif
465 
466 namespace rti { namespace flat {
467 
468 namespace detail {
469 
470 inline rti::flat::offset_t ptrdiff(unsigned char *a, unsigned char *b)
471 {
472  RTI_FLAT_ASSERT(a - b < RTI_XCDR_MAX_SERIALIZED_SIZE, return 0);
473 
474  return static_cast<rti::flat::offset_t>(a - b);
475 }
476 
477 }
478 
479 // Forward declaration
480 template <typename T, unsigned int N>
481 class FinalArrayOffset;
482 
489 class OffsetBase {
490 public:
491 
509  bool is_null() const
510  {
511  return sample_ == NULL;
512  }
513 
522  bool is_cpp_compatible() const
523  {
524  // Derived classes may indicate whether
525  // a type is cpp-compatible
526  return false;
527  }
528 
534  unsigned char * get_buffer()
535  {
536  if (is_null()) {
537  return NULL;
538  }
539  return stream_.current_position();
540  }
541 
554  const unsigned char * get_buffer() const
555  {
556  if (is_null()) {
557  return NULL;
558  }
559  return stream_.current_position();
560  }
561 
568  offset_t get_buffer_size() const
569  {
570  RTI_FLAT_OFFSET_CHECK_NOT_NULL(return 0);
571  return stream_.total_size();
572  }
573 
579  friend bool operator<(
580  const OffsetBase & s1,
581  const OffsetBase & s2) {
582  return s1.get_buffer() < s2.get_buffer();
583  }
584 
590  friend bool operator > (
591  const OffsetBase & s1,
592  const OffsetBase & s2) {
593  return s1.get_buffer() > s2.get_buffer();
594  }
595 
601  friend bool operator <= (
602  const OffsetBase & s1,
603  const OffsetBase & s2) {
604  return s1.get_buffer() <= s2.get_buffer();
605  }
606 
612  friend bool operator >= (
613  const OffsetBase & s1,
614  const OffsetBase & s2) {
615  return s1.get_buffer() >= s2.get_buffer();
616  }
617 
623  friend bool operator == (
624  const OffsetBase & s1,
625  const OffsetBase & s2) {
626  return s1.get_buffer() == s2.get_buffer();
627  }
628 
634  friend bool operator != (
635  const OffsetBase & s1,
636  const OffsetBase & s2) {
637  return !(s1 == s2);
638  }
639 
640 protected:
641 
642  OffsetBase() :
643  sample_(NULL),
644  absolute_offset_(0)
645  {
646  }
647 
648  OffsetBase(
649  SampleBase *sample,
650  offset_t absolute_offset,
651  offset_t serialized_size)
652  : sample_(sample),
653  absolute_offset_(absolute_offset)
654  {
655  // In modern C++ this throws PreconditionNotMetError; in traditional
656  // C++, this ends the constructor leaving the object in a state such
657  // that is_null() is true.
658  RTI_FLAT_CHECK_PRECONDITION(sample != NULL, return);
659 
660  sample_->initialize_stream(
661  stream_.c_stream(),
662  absolute_offset_,
663  serialized_size);
664  }
665 
666  // Gets the value of a primitive member at the specified relative Offset
667  template <typename U>
668  U deserialize(offset_t member_offset) const
669  {
670  RTI_FLAT_OFFSET_CHECK_NOT_NULL(return U());
671  RTI_FLAT_ASSERT(stream_.check_size(member_offset + static_cast<offset_t>(sizeof(U))), return U());
672 
673  rti::xcdr::Stream::Memento stream_memento(stream_);
674  stream_.skip_fast(member_offset);
675  return stream_.deserialize_fast<U>();
676  }
677 
678  // Sets the value of a primitive member at the specified relative Offset
679  template <typename U>
680  bool serialize(offset_t member_offset, U value)
681  {
682  RTI_FLAT_OFFSET_CHECK_NOT_NULL(return false);
683  RTI_FLAT_ASSERT(stream_.check_size(member_offset + static_cast<offset_t>(sizeof(U))), return false);
684 
685  rti::xcdr::Stream::Memento stream_memento(stream_);
686 
687  stream_.skip_fast(member_offset);
688  stream_.serialize_fast<U>(value);
689  return true;
690  }
691 
692  // Obtains a member at the specified relative offset
693  //
694  // U is the type of the member. U must be a subclass of Offset<U>.
695  template <typename U>
696  U get_member(offset_t relative_member_offset)
697  {
698  RTI_FLAT_OFFSET_CHECK_NOT_NULL(return U());
699 
700  return U(
701  sample_,
702  // the absolute location of the member:
703  absolute_offset_ + relative_member_offset);
704  }
705 
706  template <typename U>
707  U get_member(offset_t relative_member_offset) const
708  {
709  RTI_FLAT_OFFSET_CHECK_NOT_NULL(return U());
710 
711  return U(
712  sample_,
713  // the absolute location of the member:
714  absolute_offset_ + relative_member_offset);
715  }
716 
717 protected:
718  SampleBase *sample_; // the actual CDR buffer is in the sample
719 
720  offset_t absolute_offset_; // the position of this Offset in the buffer
721  mutable rti::xcdr::Stream stream_; // a substream that shares the same buffer
722 };
723 
731 template <typename T>
732 class FinalOffset : public OffsetBase {
733 public:
734  typedef fixed_size_type_tag_t offset_kind;
735 
736  static offset_t serialized_size_w_padding()
737  {
738  RTI_FLAT_ASSERT(T::serialized_size(0) > 0, return 0);
739  RTI_FLAT_ASSERT(T::required_alignment > 0, return 0);
740 
741  const offset_t element_size = T::serialized_size(0);
742  if (element_size % T::required_alignment != 0) {
743  return element_size + T::required_alignment
744  - element_size % T::required_alignment;
745  } else {
746  return element_size;
747  }
748  }
749 
750  bool is_cpp_compatible() const // override
751  {
752  return !stream_.needs_byte_swap()
753  && rti::xcdr::has_cpp_friendly_cdr_layout<
754  typename rti::flat::flat_type_traits<T>::flat_type>();
755  }
756 
757 protected:
758  FinalOffset()
759  {
760  }
761 
762  // Creates an Offset within the sample's CDR buffer at the specified
763  // absolute offset
764  //
765  // This overload requires T::serialized_size(offset_t)
766  //
767  FinalOffset(SampleBase *sample, offset_t absolute_offset)
768  : OffsetBase(
769  sample,
770  absolute_offset,
771  T::serialized_size(absolute_offset))
772  {
773  }
774 
775  // Gets the value of a primitive member at the specified relative offset
776  // relative_member_offsets - the 4 possible offsets depending on the this
777  // type's initial alignment
778  template <typename U>
779  U deserialize(const offset_t *relative_member_offsets) const
780  {
781  RTI_FLAT_ASSERT(relative_member_offsets != NULL, return U());
782 
783  // In a FinalOffset the stream is guaranteed to have enough space to
784  // contain all its members. There are two possible cases:
785  //
786  // - If the FinalOffset is a member of a mutable type, the member getter
787  // will ensure that the stream has enough space for the whole final
788  // type.
789  //
790  // - If the final offset is a top-level type, the type plugin ensures
791  // that the serialized buffer is large enough to contain the type.
792 
793  return OffsetBase::deserialize<U>(
794  // pick the right offset based on the initial alignment
795  get_value_for_alignment(relative_member_offsets));
796  }
797 
798  // Sets the value of a primitive member at the specified relative offset
799  template <typename U>
800  bool serialize(const offset_t *relative_member_offsets, U value)
801  {
802  RTI_FLAT_ASSERT(relative_member_offsets != NULL, return false);
803 
804  return OffsetBase::serialize<U>(
805  // pick the right offset based on the initial alignment
806  get_value_for_alignment(relative_member_offsets), value);
807  }
808 
809 
810  // Obtains a member at the specified relative offset
811  //
812  // U is the type of the member. U must be a subclass of Offset<U>.
813  template <typename U>
814  U get_member(const offset_t *relative_member_offsets)
815  {
816  RTI_FLAT_ASSERT(relative_member_offsets != NULL, return U());
817 
818  return OffsetBase::get_member<U>(
819  get_value_for_alignment(relative_member_offsets));
820  }
821 
822  template <typename U>
823  U get_member(const offset_t *relative_member_offsets) const
824  {
825  RTI_FLAT_ASSERT(relative_member_offsets != NULL, return U());
826 
827  return OffsetBase::get_member<U>(
828  get_value_for_alignment(relative_member_offsets));
829  }
830 
831  // Returns an FinalArrayOffset located within this Offset
832  template <typename U, unsigned int N>
833  FinalArrayOffset<U, N> get_array_member(
834  const offset_t *relative_member_offsets,
835  const offset_t *first_element_sizes,
836  offset_t element_size)
837  {
838  typedef FinalArrayOffset<U, N> ArrayType;
839 
840  RTI_FLAT_ASSERT(relative_member_offsets != NULL, return ArrayType());
841  RTI_FLAT_ASSERT(first_element_sizes != NULL, return ArrayType());
842 
843  RTI_FLAT_OFFSET_CHECK_NOT_NULL(return ArrayType());
844 
845  return ArrayType(
846  sample_,
847  // the absolute location of the member:
848  absolute_offset_ + get_value_for_alignment(relative_member_offsets),
849  // the size of the first element, which can differ from the rest
850  get_value_for_alignment(first_element_sizes),
851  // the size of every other element
852  element_size);
853  }
854 
855  template <typename U, unsigned int N>
856  FinalArrayOffset<U, N> get_array_member(
857  const offset_t *relative_member_offsets,
858  const offset_t *first_element_sizes,
859  offset_t element_size) const
860  {
861  typedef FinalArrayOffset<U, N> ArrayType;
862 
863  RTI_FLAT_ASSERT(relative_member_offsets != NULL, return ArrayType());
864  RTI_FLAT_ASSERT(first_element_sizes != NULL, return ArrayType());
865 
866  RTI_FLAT_OFFSET_CHECK_NOT_NULL(return ArrayType());
867  return ArrayType(
868  sample_,
869  // the absolute location of the member:
870  absolute_offset_ + get_value_for_alignment(relative_member_offsets),
871  // the size of the first element, which can differ from the rest
872  get_value_for_alignment(first_element_sizes),
873  // the size of every other element
874  element_size);
875  }
876 
877 private:
878  // A member's relative offset or an array's first element size
879  // may be different depending on the alignment of the position in the CDR
880  // buffer of the type that contains them (this). These values are passed
881  // to get_member or get_array_member as an array of 4 possible values. This
882  // function picks the right one based on the alingmenet of absolute_offset_
883  offset_t get_value_for_alignment(const offset_t *values_per_alignment) const
884  {
885  return values_per_alignment[absolute_offset_ % 4];
886  }
887 };
888 
889 struct MutableOffsetHelper {
890  // Obtains the size of a mutable struct located at the absolute_offset of
891  // a FlatData sample
892  static offset_t calculate_serialized_size(
893  rti::flat::SampleBase *sample,
894  offset_t absolute_offset,
895  offset_t)
896  {
897  RTI_FLAT_ASSERT(sample != NULL, return 0);
898 
899  return RTIXCdrFlatSample_getMutableSampleSize(
900  sample->get_buffer(),
901  absolute_offset);
902  }
903 };
904 
912 class MutableOffset : public OffsetBase {
913 public:
914  typedef variable_size_type_tag_t offset_kind;
915  typedef MutableOffsetHelper Helper;
916 
917 protected:
918  MutableOffset()
919  {
920  }
921 
923  SampleBase *sample,
924  offset_t absolute_offset,
925  offset_t serialized_size)
926  : OffsetBase(
927  sample,
928  absolute_offset,
929  serialized_size)
930  {
931  }
932 
933  template <typename U>
934  U deserialize(member_id_t member_id, U default_val = U()) const
935  {
936  RTI_FLAT_OFFSET_CHECK_NOT_NULL(return U());
937 
938  rti::xcdr::Stream::Memento stream_memento(stream_);
939 
940  offset_t member_size = 0;
941  if (!RTIXCdrStream_findV2MutableSampleMember(
942  &stream_.c_stream(),
943  member_id,
944  &member_size)) {
945  return default_val;
946  }
947 
948  return stream_.deserialize_fast<U>();
949  }
950 
951  // Sets the value of a primitive member at the specified relative offset
952  template <typename U>
953  bool serialize(member_id_t member_id, U value)
954  {
955  RTI_FLAT_OFFSET_CHECK_NOT_NULL(return false);
956 
957  rti::xcdr::Stream::Memento stream_memento(stream_);
958 
959  offset_t member_size = 0;
960  if (!RTIXCdrStream_findV2MutableSampleMember(
961  &stream_.c_stream(),
962  member_id,
963  &member_size)) {
964  return false;
965  }
966 
967  stream_.serialize_fast<U>(value);
968  return true;
969  }
970 
971  template <typename U>
972  U get_member(member_id_t member_id) const
973  {
974  RTI_FLAT_OFFSET_CHECK_NOT_NULL(return U());
975 
976  rti::xcdr::Stream::Memento stream_memento(stream_);
977 
978  offset_t member_size = 0;
979  if (!RTIXCdrStream_findV2MutableSampleMember(
980  &stream_.c_stream(),
981  member_id,
982  &member_size)) {
983  return U();
984  }
985 
986  return get_member_impl<U>(
987  // absolute offset to the found member
988  detail::ptrdiff(stream_.current_position(), sample_->get_buffer()),
989  member_size,
990  typename U::offset_kind());
991  }
992 
993 private:
994  template <typename U>
995  U get_member_impl(
996  offset_t absolute_member_offset,
997  offset_t member_size,
998  variable_size_type_tag_t) const
999  {
1000  RTI_FLAT_ASSERT(absolute_member_offset > 0, return U());
1001 
1002  // VariableOffsets receive a member_size
1003  return U(sample_, absolute_member_offset, member_size);
1004  }
1005 
1006  template <typename U>
1007  U get_member_impl(
1008  offset_t absolute_member_offset,
1009  offset_t member_size,
1010  fixed_size_type_tag_t) const
1011  {
1012  (void) member_size; // supress unused-param warning in release mode
1013 
1014  RTI_FLAT_ASSERT(absolute_member_offset > 0, return U());
1015  RTI_FLAT_ASSERT(member_size == U::serialized_size(0), return U());
1016 
1017  // FixedOffsets do not receive a member_size (it's already known)
1018  return U(sample_, absolute_member_offset);
1019  }
1020 };
1021 
1030 template <typename T>
1032 public:
1033  typedef fixed_size_type_tag_t offset_kind;
1034 
1036  {
1037  }
1038 
1040  SampleBase *sample,
1041  offset_t absolute_offset)
1042  : OffsetBase(
1043  sample,
1044  absolute_offset,
1045  serialized_size(0))
1046  {
1047  }
1048 
1049  bool is_cpp_compatible() const
1050  {
1051  return sizeof(T) == 1 || !stream_.needs_byte_swap();
1052  }
1053 
1059  T get() const
1060  {
1061  RTI_FLAT_OFFSET_CHECK_NOT_NULL(return T());
1062  RTI_FLAT_ASSERT(stream_.check_size(sizeof(T)), return T());
1063 
1064  return stream_.deserialize_fast<T>();
1065  }
1066 
1067  static offset_t serialized_size(offset_t)
1068  {
1069  return sizeof(T);
1070  }
1071 
1072  static offset_t serialized_size_w_padding()
1073  {
1074  return serialized_size(0);
1075  }
1076 
1077 };
1078 
1095 template <typename T>
1097 public:
1098  PrimitiveOffset()
1099  {
1100  }
1101 
1103  SampleBase *sample,
1104  offset_t absolute_offset)
1106  sample,
1107  absolute_offset)
1108  {
1109  }
1110 
1116  bool set(T value)
1117  {
1118  RTI_FLAT_OFFSET_CHECK_NOT_NULL(return false);
1119  RTI_FLAT_ASSERT(this->stream_.check_size(sizeof(T)), return false);
1120 
1121  this->stream_.template serialize_fast<T>(value);
1122  return true;
1123  }
1124 };
1125 
1126 } }
1127 
1128 #endif // RTI_DDS_FLAT_FLATOFFSETS_HPP_
1129 

RTI Connext Traditional C++ API Version 6.0.1 Copyright © Sat Nov 23 2019 Real-Time Innovations, Inc