RTI Connext Traditional C++ API  Version 6.1.0
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 
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 
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>
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  RTI_FLAT_OFFSET_CHECK_NOT_NULL(return false);
753  return !stream_.needs_byte_swap()
754  && rti::xcdr::has_cpp_friendly_cdr_layout<
756  }
757 
758 protected:
759  FinalOffset()
760  {
761  }
762 
763  // Creates an Offset within the sample's CDR buffer at the specified
764  // absolute offset
765  //
766  // This overload requires T::serialized_size(offset_t)
767  //
768  FinalOffset(SampleBase *sample, offset_t absolute_offset)
769  : OffsetBase(
770  sample,
771  absolute_offset,
772  T::serialized_size(absolute_offset))
773  {
774  }
775 
776  // Gets the value of a primitive member at the specified relative offset
777  // relative_member_offsets - the 4 possible offsets depending on the this
778  // type's initial alignment
779  template <typename U>
780  U deserialize(const offset_t *relative_member_offsets) const
781  {
782  RTI_FLAT_ASSERT(relative_member_offsets != NULL, return U());
783 
784  // In a FinalOffset the stream is guaranteed to have enough space to
785  // contain all its members. There are two possible cases:
786  //
787  // - If the FinalOffset is a member of a mutable type, the member getter
788  // will ensure that the stream has enough space for the whole final
789  // type.
790  //
791  // - If the final offset is a top-level type, the type plugin ensures
792  // that the serialized buffer is large enough to contain the type.
793 
794  return OffsetBase::deserialize<U>(
795  // pick the right offset based on the initial alignment
796  get_value_for_alignment(relative_member_offsets));
797  }
798 
799  // Sets the value of a primitive member at the specified relative offset
800  template <typename U>
801  bool serialize(const offset_t *relative_member_offsets, U value)
802  {
803  RTI_FLAT_ASSERT(relative_member_offsets != NULL, return false);
804 
805  return OffsetBase::serialize<U>(
806  // pick the right offset based on the initial alignment
807  get_value_for_alignment(relative_member_offsets), value);
808  }
809 
810 
811  // Obtains a member at the specified relative offset
812  //
813  // U is the type of the member. U must be a subclass of Offset<U>.
814  template <typename U>
815  U get_member(const offset_t *relative_member_offsets)
816  {
817  RTI_FLAT_ASSERT(relative_member_offsets != NULL, return U());
818 
819  return OffsetBase::get_member<U>(
820  get_value_for_alignment(relative_member_offsets));
821  }
822 
823  template <typename U>
824  U get_member(const offset_t *relative_member_offsets) const
825  {
826  RTI_FLAT_ASSERT(relative_member_offsets != NULL, return U());
827 
828  return OffsetBase::get_member<U>(
829  get_value_for_alignment(relative_member_offsets));
830  }
831 
832  // Returns an FinalArrayOffset located within this Offset
833  template <typename U, unsigned int N>
834  FinalArrayOffset<U, N> get_array_member(
835  const offset_t *relative_member_offsets,
836  const offset_t *first_element_sizes,
837  offset_t element_size)
838  {
839  typedef FinalArrayOffset<U, N> ArrayType;
840 
841  RTI_FLAT_ASSERT(relative_member_offsets != NULL, return ArrayType());
842  RTI_FLAT_ASSERT(first_element_sizes != NULL, return ArrayType());
843 
844  RTI_FLAT_OFFSET_CHECK_NOT_NULL(return ArrayType());
845 
846  return ArrayType(
847  sample_,
848  // the absolute location of the member:
849  absolute_offset_ + get_value_for_alignment(relative_member_offsets),
850  // the size of the first element, which can differ from the rest
851  get_value_for_alignment(first_element_sizes),
852  // the size of every other element
853  element_size);
854  }
855 
856  template <typename U, unsigned int N>
857  FinalArrayOffset<U, N> get_array_member(
858  const offset_t *relative_member_offsets,
859  const offset_t *first_element_sizes,
860  offset_t element_size) const
861  {
862  typedef FinalArrayOffset<U, N> ArrayType;
863 
864  RTI_FLAT_ASSERT(relative_member_offsets != NULL, return ArrayType());
865  RTI_FLAT_ASSERT(first_element_sizes != NULL, return ArrayType());
866 
867  RTI_FLAT_OFFSET_CHECK_NOT_NULL(return ArrayType());
868  return ArrayType(
869  sample_,
870  // the absolute location of the member:
871  absolute_offset_ + get_value_for_alignment(relative_member_offsets),
872  // the size of the first element, which can differ from the rest
873  get_value_for_alignment(first_element_sizes),
874  // the size of every other element
875  element_size);
876  }
877 
878 private:
879  // A member's relative offset or an array's first element size
880  // may be different depending on the alignment of the position in the CDR
881  // buffer of the type that contains them (this). These values are passed
882  // to get_member or get_array_member as an array of 4 possible values. This
883  // function picks the right one based on the alingmenet of absolute_offset_
884  offset_t get_value_for_alignment(const offset_t *values_per_alignment) const
885  {
886  return values_per_alignment[absolute_offset_ % 4];
887  }
888 };
889 
890 struct MutableOffsetHelper {
891  // Obtains the size of a mutable struct located at the absolute_offset of
892  // a FlatData sample
893  static offset_t calculate_serialized_size(
894  rti::flat::SampleBase *sample,
895  offset_t absolute_offset,
896  offset_t)
897  {
898  RTI_FLAT_ASSERT(sample != NULL, return 0);
899 
900  return RTIXCdrFlatSample_getMutableSampleSize(
901  sample->get_buffer(),
902  absolute_offset);
903  }
904 };
905 
913 class MutableOffset : public OffsetBase {
914 public:
915  typedef variable_size_type_tag_t offset_kind;
916  typedef MutableOffsetHelper Helper;
917 
918 protected:
919  MutableOffset()
920  {
921  }
922 
924  SampleBase *sample,
925  offset_t absolute_offset,
926  offset_t serialized_size)
927  : OffsetBase(
928  sample,
929  absolute_offset,
930  serialized_size)
931  {
932  }
933 
934  template <typename U>
935  U deserialize(member_id_t member_id, U default_val = U()) const
936  {
937  RTI_FLAT_OFFSET_CHECK_NOT_NULL(return U());
938 
939  rti::xcdr::Stream::Memento stream_memento(stream_);
940 
941  offset_t member_size = 0;
942  if (!RTIXCdrStream_findV2MutableSampleMember(
943  &stream_.c_stream(),
944  member_id,
945  &member_size)) {
946  return default_val;
947  }
948 
949  return stream_.deserialize_fast<U>();
950  }
951 
952  // Sets the value of a primitive member at the specified relative offset
953  template <typename U>
954  bool serialize(member_id_t member_id, U value)
955  {
956  RTI_FLAT_OFFSET_CHECK_NOT_NULL(return false);
957 
958  rti::xcdr::Stream::Memento stream_memento(stream_);
959 
960  offset_t member_size = 0;
961  if (!RTIXCdrStream_findV2MutableSampleMember(
962  &stream_.c_stream(),
963  member_id,
964  &member_size)) {
965  return false;
966  }
967 
968  stream_.serialize_fast<U>(value);
969  return true;
970  }
971 
972  template <typename U>
973  U get_member(member_id_t member_id) const
974  {
975  RTI_FLAT_OFFSET_CHECK_NOT_NULL(return U());
976 
977  rti::xcdr::Stream::Memento stream_memento(stream_);
978 
979  offset_t member_size = 0;
980  if (!RTIXCdrStream_findV2MutableSampleMember(
981  &stream_.c_stream(),
982  member_id,
983  &member_size)) {
984  return U();
985  }
986 
987  return get_member_impl<U>(
988  // absolute offset to the found member
989  detail::ptrdiff(stream_.current_position(), sample_->get_buffer()),
990  member_size,
991  typename U::offset_kind());
992  }
993 
994 private:
995  template <typename U>
996  U get_member_impl(
997  offset_t absolute_member_offset,
998  offset_t member_size,
999  variable_size_type_tag_t) const
1000  {
1001  RTI_FLAT_ASSERT(absolute_member_offset > 0, return U());
1002 
1003  // VariableOffsets receive a member_size
1004  return U(sample_, absolute_member_offset, member_size);
1005  }
1006 
1007  template <typename U>
1008  U get_member_impl(
1009  offset_t absolute_member_offset,
1010  offset_t member_size,
1011  fixed_size_type_tag_t) const
1012  {
1013  (void) member_size; // supress unused-param warning in release mode
1014 
1015  RTI_FLAT_ASSERT(absolute_member_offset > 0, return U());
1016  RTI_FLAT_ASSERT(member_size == U::serialized_size(0), return U());
1017 
1018  // FixedOffsets do not receive a member_size (it's already known)
1019  return U(sample_, absolute_member_offset);
1020  }
1021 };
1022 
1031 template <typename T>
1033 public:
1034  typedef fixed_size_type_tag_t offset_kind;
1035 
1037  {
1038  }
1039 
1041  SampleBase *sample,
1042  offset_t absolute_offset)
1043  : OffsetBase(
1044  sample,
1045  absolute_offset,
1046  serialized_size(0))
1047  {
1048  }
1049 
1050  bool is_cpp_compatible() const
1051  {
1052  RTI_FLAT_OFFSET_CHECK_NOT_NULL(return false);
1053  return sizeof(T) == 1 || !stream_.needs_byte_swap();
1054  }
1055 
1061  T get() const
1062  {
1063  RTI_FLAT_OFFSET_CHECK_NOT_NULL(return T());
1064  RTI_FLAT_ASSERT(stream_.check_size(sizeof(T)), return T());
1065 
1066  return stream_.deserialize_fast<T>();
1067  }
1068 
1069  static offset_t serialized_size(offset_t)
1070  {
1071  return sizeof(T);
1072  }
1073 
1074  static offset_t serialized_size_w_padding()
1075  {
1076  return serialized_size(0);
1077  }
1078 
1079 };
1080 
1097 template <typename T>
1099 public:
1100  PrimitiveOffset()
1101  {
1102  }
1103 
1105  SampleBase *sample,
1106  offset_t absolute_offset)
1108  sample,
1109  absolute_offset)
1110  {
1111  }
1112 
1118  bool set(T value)
1119  {
1120  RTI_FLAT_OFFSET_CHECK_NOT_NULL(return false);
1121  RTI_FLAT_ASSERT(this->stream_.check_size(sizeof(T)), return false);
1122 
1123  this->stream_.template serialize_fast<T>(value);
1124  return true;
1125  }
1126 };
1127 
1128 } }
1129 
1130 #endif // RTI_DDS_FLAT_FLATOFFSETS_HPP_
1131 
Represents the Offset to an arbitrary user-defined FlatData mutable IDL struct.
Definition: Offset.hpp:203
Represents the Offset to an arbitrary user-defined FlatData mutable IDL union.
Definition: Offset.hpp:375
friend bool operator==(const OffsetBase &s1, const OffsetBase &s2)
Determines if two offets point to the same position.
Definition: Offset.hpp:623
An Offset to an optional primitive member.
Definition: Offset.hpp:1098
Offset to a sequence of primitive elements.
Definition: SequenceOffsets.hpp:134
const unsigned char * get_buffer() const
Gets this member&#39;s position in the buffer.
Definition: Offset.hpp:554
OffsetType::ConstOffset ConstOffset
The related read-only Offset type.
Definition: FlatSample.hpp:162
friend bool operator!=(const OffsetBase &s1, const OffsetBase &s2)
Determines if two offets point to different positions.
Definition: Offset.hpp:634
Given a Sample, an Offset or a Builder, it allows obtaining the other types.
Definition: FlatSample.hpp:340
Offset to an array of primitive elements.
Definition: SequenceOffsets.hpp:208
Offset to an array of variable-size elements.
Definition: SequenceOffsets.hpp:567
Base class of all Offset types.
Definition: Offset.hpp:489
const rti::flat::PrimitiveArrayOffset< int32_t, 10 > my_primitive_array() const
Retrieves a const Offset to a primitive array.
The base class of all Offsets to a final struct type.
Definition: Offset.hpp:732
MyFlatMutableOffset()
Creates a null Offset.
Definition: Offset.hpp:220
friend bool operator<(const OffsetBase &s1, const OffsetBase &s2)
Compares two Offsets.
Definition: Offset.hpp:579
MyFlatUnionOffset()
Creates a null Offset.
Definition: Offset.hpp:388
FlatFinalBar::ConstOffset my_complex() const
Retrieves a const Offset to a complex member.
Offset to a string.
Definition: SequenceOffsets.hpp:251
Offset to an array of final elements.
Definition: Offset.hpp:481
OffsetType Offset
The related Offset type.
Definition: FlatSample.hpp:155
Represents the Offset to an arbitrary user-defined FlatData final IDL struct.
Definition: Offset.hpp:125
friend bool operator>=(const OffsetBase &s1, const OffsetBase &s2)
Compares two Offsets.
Definition: Offset.hpp:612
friend bool operator<=(const OffsetBase &s1, const OffsetBase &s2)
Compares two Offsets.
Definition: Offset.hpp:601
Offset to an array of final elements.
Definition: SequenceOffsets.hpp:715
MyFlatUnionConstOffset ConstOffset
The equivalent read-only Offset type.
Definition: Offset.hpp:381
bool is_null() const
Indicates whether this Offset doesn&#39;t point to a valid element.
Definition: Offset.hpp:509
friend bool operator>(const OffsetBase &s1, const OffsetBase &s2)
Compares two Offsets.
Definition: Offset.hpp:590
rti::flat::FinalArrayOffset< FlatFinalBar::ConstOffset, 10 > my_complex_array() const
Retrieves a const Offset to a complex array.
MyFlatMutableConstOffset ConstOffset
The equivalent read-only Offset type.
Definition: Offset.hpp:213
int32_t my_primitive() const
Retrieves the value for a primitive member.
offset_t get_buffer_size() const
Gets the size, in bytes, of this member in the buffer.
Definition: Offset.hpp:568
The base class of all Offsets to a final struct type.
Definition: Offset.hpp:913
Definition: AggregationBuilders.hpp:17
A const Offset to an optional primitive member.
Definition: Offset.hpp:1032
Offset to a sequence of non-primitive elements.
Definition: SequenceOffsets.hpp:459
MyFlatFinalOffset()
Creates a null Offset.
Definition: Offset.hpp:142
MyFlatFinalConstOffset ConstOffset
The equivalent read-only Offset type.
Definition: Offset.hpp:135
bool is_cpp_compatible() const
Indicates whether rti::flat::plain_cast() is possible.
Definition: Offset.hpp:522