RTI Connext Traditional C++ API  Version 7.0.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
887  [absolute_offset_ % RTI_XCDR_MAX_XCDR2_ALIGNMENT];
888  }
889 };
890 
891 struct MutableOffsetHelper {
892  // Obtains the size of a mutable struct located at the absolute_offset of
893  // a FlatData sample
894  static offset_t calculate_serialized_size(
895  rti::flat::SampleBase *sample,
896  offset_t absolute_offset,
897  offset_t)
898  {
899  RTI_FLAT_ASSERT(sample != NULL, return 0);
900 
901  return RTIXCdrFlatSample_getMutableSampleSize(
902  sample->get_buffer(),
903  absolute_offset);
904  }
905 };
906 
914 class MutableOffset : public OffsetBase {
915 public:
916  typedef variable_size_type_tag_t offset_kind;
917  typedef MutableOffsetHelper Helper;
918 
919 protected:
920  MutableOffset()
921  {
922  }
923 
925  SampleBase *sample,
926  offset_t absolute_offset,
927  offset_t serialized_size)
928  : OffsetBase(
929  sample,
930  absolute_offset,
931  serialized_size)
932  {
933  }
934 
935  template <typename U>
936  U deserialize(member_id_t member_id, U default_val = U()) const
937  {
938  RTI_FLAT_OFFSET_CHECK_NOT_NULL(return U());
939 
940  rti::xcdr::Stream::Memento stream_memento(stream_);
941 
942  offset_t member_size = 0;
943  if (!RTIXCdrStream_findV2MutableSampleMember(
944  &stream_.c_stream(),
945  member_id,
946  &member_size)) {
947  return default_val;
948  }
949 
950  return stream_.deserialize_fast<U>();
951  }
952 
953  // Sets the value of a primitive member at the specified relative offset
954  template <typename U>
955  bool serialize(member_id_t member_id, U value)
956  {
957  RTI_FLAT_OFFSET_CHECK_NOT_NULL(return false);
958 
959  rti::xcdr::Stream::Memento stream_memento(stream_);
960 
961  offset_t member_size = 0;
962  if (!RTIXCdrStream_findV2MutableSampleMember(
963  &stream_.c_stream(),
964  member_id,
965  &member_size)) {
966  return false;
967  }
968 
969  stream_.serialize_fast<U>(value);
970  return true;
971  }
972 
973  template <typename U>
974  U get_member(member_id_t member_id) const
975  {
976  RTI_FLAT_OFFSET_CHECK_NOT_NULL(return U());
977 
978  rti::xcdr::Stream::Memento stream_memento(stream_);
979 
980  offset_t member_size = 0;
981  if (!RTIXCdrStream_findV2MutableSampleMember(
982  &stream_.c_stream(),
983  member_id,
984  &member_size)) {
985  return U();
986  }
987 
988  return get_member_impl<U>(
989  // absolute offset to the found member
990  detail::ptrdiff(stream_.current_position(), sample_->get_buffer()),
991  member_size,
992  typename U::offset_kind());
993  }
994 
995 private:
996  template <typename U>
997  U get_member_impl(
998  offset_t absolute_member_offset,
999  offset_t member_size,
1000  variable_size_type_tag_t) const
1001  {
1002  RTI_FLAT_ASSERT(absolute_member_offset > 0, return U());
1003 
1004  // VariableOffsets receive a member_size
1005  return U(sample_, absolute_member_offset, member_size);
1006  }
1007 
1008  template <typename U>
1009  U get_member_impl(
1010  offset_t absolute_member_offset,
1011  offset_t member_size,
1012  fixed_size_type_tag_t) const
1013  {
1014  (void) member_size; // supress unused-param warning in release mode
1015 
1016  RTI_FLAT_ASSERT(absolute_member_offset > 0, return U());
1017  RTI_FLAT_ASSERT(member_size == U::serialized_size(0), return U());
1018 
1019  // FixedOffsets do not receive a member_size (it's already known)
1020  return U(sample_, absolute_member_offset);
1021  }
1022 };
1023 
1032 template <typename T>
1034 public:
1035  typedef fixed_size_type_tag_t offset_kind;
1036 
1038  {
1039  }
1040 
1042  SampleBase *sample,
1043  offset_t absolute_offset)
1044  : OffsetBase(
1045  sample,
1046  absolute_offset,
1047  serialized_size(0))
1048  {
1049  }
1050 
1051  bool is_cpp_compatible() const
1052  {
1053  RTI_FLAT_OFFSET_CHECK_NOT_NULL(return false);
1054  return sizeof(T) == 1 || !stream_.needs_byte_swap();
1055  }
1056 
1062  T get() const
1063  {
1064  RTI_FLAT_OFFSET_CHECK_NOT_NULL(return T());
1065  RTI_FLAT_ASSERT(stream_.check_size(sizeof(T)), return T());
1066 
1067  return stream_.deserialize_fast<T>();
1068  }
1069 
1070  static offset_t serialized_size(offset_t)
1071  {
1072  return sizeof(T);
1073  }
1074 
1075  static offset_t serialized_size_w_padding()
1076  {
1077  return serialized_size(0);
1078  }
1079 
1080 };
1081 
1098 template <typename T>
1100 public:
1101  PrimitiveOffset()
1102  {
1103  }
1104 
1106  SampleBase *sample,
1107  offset_t absolute_offset)
1109  sample,
1110  absolute_offset)
1111  {
1112  }
1113 
1119  bool set(T value)
1120  {
1121  RTI_FLAT_OFFSET_CHECK_NOT_NULL(return false);
1122  RTI_FLAT_ASSERT(this->stream_.check_size(sizeof(T)), return false);
1123 
1124  this->stream_.template serialize_fast<T>(value);
1125  return true;
1126  }
1127 };
1128 
1129 } }
1130 
1131 #endif // RTI_DDS_FLAT_FLATOFFSETS_HPP_
1132 
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:1099
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:220
Offset to an array of variable-size elements.
Definition: SequenceOffsets.hpp:580
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:263
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:728
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:914
Definition: AggregationBuilders.hpp:17
A const Offset to an optional primitive member.
Definition: Offset.hpp:1033
Offset to a sequence of non-primitive elements.
Definition: SequenceOffsets.hpp:471
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