RTI Connext Traditional C++ API  Version 6.1.0
Stream.hpp
1 /* $Id$
2 
3 (c) Copyright, Real-Time Innovations, 2018.
4 All rights reserved.
5 
6 No duplications, whole or partial, manual or electronic, may be made
7 without express written permission. Any such copies, or
8 revisions thereof, must display this notice unaltered.
9 This code contains trade secrets of Real-Time Innovations, Inc.
10 
11 ============================================================================= */
12 
13 #ifndef RTI_XCDR_STREAM_HPP_
14 #define RTI_XCDR_STREAM_HPP_
15 
16 #include "xcdr/xcdr_stream.h"
17 
18 namespace rti { namespace xcdr {
19 
20 
21 #define RTI_XCDR_SPECIALIZE_PRIMITIVE_TYPE_TRAITS_BODY(\
22  TYPE,\
23  CDR_TYPE,\
24  SERIALIZE_MACRO)\
25  static void serialize_fast(RTIXCdrStream *stream, const TYPE* v)\
26  {\
27  RTIXCdrStream_ ## SERIALIZE_MACRO ## ByteFast(stream, (CDR_TYPE *) v);\
28  }\
29  static void deserialize_fast(RTIXCdrStream *stream, TYPE* v)\
30  {\
31  RTIXCdrStream_de ## SERIALIZE_MACRO ## ByteFast(stream, (CDR_TYPE *) v);\
32  }\
33  static bool serialize(RTIXCdrStream *stream, const TYPE* v)\
34  {\
35  return RTIXCdrStream_ ## SERIALIZE_MACRO ## Byte(stream, (CDR_TYPE *) v, RTI_XCDR_TRUE);\
36  }\
37  static bool deserialize(RTIXCdrStream *stream, TYPE* v)\
38  {\
39  return RTIXCdrStream_de ## SERIALIZE_MACRO ## Byte(stream, (CDR_TYPE *) v, RTI_XCDR_TRUE);\
40  }\
41 
42 #define RTI_XCDR_SPECIALIZE_PRIMITIVE_TYPE_TRAITS(\
43  TYPE,\
44  CDR_TYPE,\
45  SERIALIZE_MACRO)\
46 template <>\
47 struct primitive_type_traits<TYPE> {\
48 RTI_XCDR_SPECIALIZE_PRIMITIVE_TYPE_TRAITS_BODY(TYPE, CDR_TYPE, SERIALIZE_MACRO)\
49 }
50 
51 #define RTI_XCDR_SPECIALIZE_PRIMITIVE_TYPE_TRAITS_W_ALIGNMENT_PARAM(\
52  TYPE,\
53  CDR_TYPE,\
54  SERIALIZE_MACRO,\
55  ALIGNMENT)\
56 template <>\
57 struct primitive_type_traits<TYPE> {\
58  static void serialize_fast(RTIXCdrStream *stream, const TYPE* v)\
59  {\
60  RTIXCdrStream_ ## SERIALIZE_MACRO ## ByteFast(stream, (CDR_TYPE *) v);\
61  }\
62  static void deserialize_fast(RTIXCdrStream *stream, TYPE* v)\
63  {\
64  RTIXCdrStream_de ## SERIALIZE_MACRO ## ByteFast(stream, (CDR_TYPE *) v);\
65  }\
66  static bool serialize(RTIXCdrStream *stream, const TYPE* v)\
67  {\
68  return RTIXCdrStream_ ## SERIALIZE_MACRO ## Byte(stream, (CDR_TYPE *) v, RTI_XCDR_TRUE, ALIGNMENT);\
69  }\
70  static bool deserialize(RTIXCdrStream *stream, TYPE* v)\
71  {\
72  return RTIXCdrStream_de ## SERIALIZE_MACRO ## Byte(stream, (CDR_TYPE *) v, RTI_XCDR_TRUE, ALIGNMENT);\
73  }\
74 }
75 
76 #define RTI_XCDR_SPECIALIZE_PRIMITIVE_TYPE_TRAITS_NO_ALIGN_PARAM(\
77  TYPE,\
78  CDR_TYPE,\
79  SERIALIZE_MACRO)\
80 template <>\
81 struct primitive_type_traits<TYPE> {\
82  static void serialize_fast(RTIXCdrStream *stream, const TYPE* v)\
83  {\
84  RTIXCdrStream_ ## SERIALIZE_MACRO ## ByteFast(stream, (CDR_TYPE *) v);\
85  }\
86  static void deserialize_fast(RTIXCdrStream *stream, TYPE* v)\
87  {\
88  RTIXCdrStream_de ## SERIALIZE_MACRO ## ByteFast(stream, (CDR_TYPE *) v);\
89  }\
90  static bool serialize(RTIXCdrStream *stream, const TYPE* v)\
91  {\
92  return RTIXCdrStream_ ## SERIALIZE_MACRO ## Byte(stream, (CDR_TYPE *) v);\
93  }\
94  static bool deserialize(RTIXCdrStream *stream, TYPE* v)\
95  {\
96  return RTIXCdrStream_de ## SERIALIZE_MACRO ## Byte(stream, (CDR_TYPE *) v);\
97  }\
98 }
99 
100 // Base case handles T as an 4-byte integer (this is necessary for traditional
101 // C++ enums as well as C++11 enum classes)
102 template <typename T>
103 struct primitive_type_traits {
104  RTI_XCDR_SPECIALIZE_PRIMITIVE_TYPE_TRAITS_BODY(T, RTIXCdr4Byte, serialize4)
105 };
106 
107 RTI_XCDR_SPECIALIZE_PRIMITIVE_TYPE_TRAITS_NO_ALIGN_PARAM(\
108  char, RTIXCdr1Byte, serialize1);
109 
110 // The API can work with fixed-width integers (dds_cpp.2.0) or
111 // RTI-defined integers (dds_cpp.1.0). We need to make this distinction because
112 // on some platforms these types may not be exactly the same as far as template
113 // resolution. That is, compilers may or may not pick the template
114 // specialization for int32_t for an instantiation with int.
115 //
116 // If we define only one (e.g. int32_t) some compilers won't find a suitable
117 // definition for int. If we define both, some compilers will find duplicate
118 // definitions for int/int32_t.
119 #if !defined(RTI_AVOID_FIXED_WIDTH_INTEGERS)
120 RTI_XCDR_SPECIALIZE_PRIMITIVE_TYPE_TRAITS_NO_ALIGN_PARAM(\
121  uint8_t, RTIXCdr1Byte, serialize1);
122 
123 RTI_XCDR_SPECIALIZE_PRIMITIVE_TYPE_TRAITS(\
124  int16_t, RTIXCdr2Byte, serialize2);
125 RTI_XCDR_SPECIALIZE_PRIMITIVE_TYPE_TRAITS(\
126  uint16_t, RTIXCdr2Byte, serialize2);
127 
128 RTI_XCDR_SPECIALIZE_PRIMITIVE_TYPE_TRAITS(\
129  int32_t, RTIXCdr4Byte, serialize4);
130 RTI_XCDR_SPECIALIZE_PRIMITIVE_TYPE_TRAITS(\
131  uint32_t, RTIXCdr4Byte, serialize4);
132 
133 typedef uint32_t length_t;
134 #else
135 RTI_XCDR_SPECIALIZE_PRIMITIVE_TYPE_TRAITS_NO_ALIGN_PARAM(\
136  unsigned char, RTIXCdr1Byte, serialize1);
137 
138 RTI_XCDR_SPECIALIZE_PRIMITIVE_TYPE_TRAITS(\
139  short, RTIXCdr2Byte, serialize2);
140 RTI_XCDR_SPECIALIZE_PRIMITIVE_TYPE_TRAITS(\
141  unsigned short, RTIXCdr2Byte, serialize2);
142 
143 // int and unsigned int, as well as enum are handled by the general case
144 
145 typedef unsigned int length_t;
146 #endif
147 
148 RTI_XCDR_SPECIALIZE_PRIMITIVE_TYPE_TRAITS(\
149  float, RTIXCdr4Byte, serialize4);
150 
151 RTI_XCDR_SPECIALIZE_PRIMITIVE_TYPE_TRAITS_W_ALIGNMENT_PARAM(\
152  DDS_LongLong, RTIXCdr8Byte, serialize8, 4);
153 
154 RTI_XCDR_SPECIALIZE_PRIMITIVE_TYPE_TRAITS_W_ALIGNMENT_PARAM(\
155  DDS_UnsignedLongLong, RTIXCdr8Byte, serialize8, 4);
156 RTI_XCDR_SPECIALIZE_PRIMITIVE_TYPE_TRAITS_W_ALIGNMENT_PARAM(\
157  double, RTIXCdr8Byte, serialize8, 4);
158 
159 // RTI_XCDR_SPECIALIZE_PRIMITIVE_TYPE_TRAITS(
160 // rti::core::LongDouble, RTI_CDR_LONG_DOUBLE_TYPE, RTIXCdr16Byte, serialize16Byte);
161 
162 template <typename T>
163 void serialize_fast(RTIXCdrStream& stream, const T& value)
164 {
165  primitive_type_traits<T>::serialize_fast(&stream, &value);
166 }
167 
168 template <typename T>
169 void deserialize_fast(RTIXCdrStream& stream, T& value)
170 {
171  primitive_type_traits<T>::deserialize_fast(&stream, &value);
172 }
173 
174 class Stream {
175 public:
176  Stream()
177  {
178  RTIXCdrStream_set(&stream_, NULL, 0);
179  }
180 
181  explicit Stream(const RTIXCdrStream& c_stream)
182  {
183  stream_ = c_stream; // shallow assign
184  }
185 
186  // Creates a new stream that shares the same buffer and current position
187  // as another Stream
188  Stream(const Stream& other)
189  {
190  stream_ = other.stream_; // shallow assign
191  }
192 
193  // Creates a new Stream from an existing already-initialized buffer, whose
194  // encapsulation has already been set
195  Stream(
196  unsigned char *buffer,
197  length_t size,
198  length_t offset)
199  {
200  RTIXCdrFlatData_initializeStream(
201  &stream_,
202  buffer,
203  offset,
204  size);
205  }
206 
207  bool skip(length_t size)
208  {
209  if (!check_size(size)) {
210  return false;
211  }
212  RTIXCdrStream_increaseCurrentPosition(&stream_, size);
213  return true;
214  }
215 
216  void skip_fast(length_t size)
217  {
218  RTIXCdrStream_increaseCurrentPosition(&stream_, size);
219  }
220 
221  void skip_back(length_t bytes)
222  {
223  RTIXCdrStream_increaseCurrentPosition(
224  &stream_,
225  -static_cast<int>(bytes));
226  }
227 
228  unsigned char * buffer()
229  {
230  return reinterpret_cast<unsigned char*>(stream_._buffer);
231  }
232 
233  const unsigned char * buffer() const
234  {
235  return reinterpret_cast<unsigned char*>(stream_._buffer);
236  }
237 
238  unsigned char * current_position()
239  {
240  return reinterpret_cast<unsigned char*>(
241  RTIXCdrStream_getCurrentPosition(&stream_));
242  }
243 
244  void current_position(unsigned char * pos)
245  {
246  RTIXCdrStream_setCurrentPosition(
247  &stream_,
248  reinterpret_cast<char*>(pos));
249  }
250 
251  length_t used_size() const
252  {
253  return static_cast<length_t>(
254  RTIXCdrStream_getCurrentPosition(&stream_) - stream_._buffer);
255  }
256 
257  length_t remaining_size() const
258  {
259  return total_size() - used_size();
260  }
261 
262  length_t total_size() const
263  {
264  return stream_._bufferLength;
265  }
266 
267  bool needs_byte_swap() const
268  {
269  return stream_._needByteSwap == RTI_XCDR_TRUE;
270  }
271 
272  template <typename T>
273  bool serialize(T value)
274  {
275  return primitive_type_traits<T>::serialize(&stream_, &value);
276  }
277 
278  template <typename T>
279  void serialize_fast(T value)
280  {
281  primitive_type_traits<T>::serialize_fast(&stream_, &value);
282  }
283 
284  template <typename T>
285  bool serialize_no_align(T value)
286  {
287  if (!check_size(sizeof(T))) {
288  return false;
289  }
290  primitive_type_traits<T>::serialize_fast(&stream_, &value);
291  return true;
292  }
293 
294  template <typename T>
295  T deserialize_fast()
296  {
297  T value;
298  primitive_type_traits<T>::deserialize_fast(&stream_, &value);
299  return value;
300  }
301 
302  void serialize_fast(const void *array, length_t bytes)
303  {
304  RTIXCdrStream_serializeNByteFast(&stream_, array, bytes);
305  }
306 
307  char * serialize_dheader()
308  {
309  return RTIXCdrStream_serializeDHeader(&stream_);
310  }
311 
312  bool finish_dheader(char *dheader_position)
313  {
314  return RTIXCdrStream_serializeDHeaderLength(&stream_, dheader_position)
315  == RTI_XCDR_TRUE;
316  }
317 
318  bool serialize_emheader(
319  char*& position,
320  RTIXCdrUnsignedLong parameter_id,
321  RTIXCdrUnsignedLong lc,
322  bool must_understand = false)
323  {
324  RTIXCdrBoolean failure = 0;
325  position = RTIXCdrStream_serializeV2ParameterHeader(
326  &stream_,
327  &failure,
328  parameter_id,
329  must_understand ? RTI_XCDR_TRUE : RTI_XCDR_FALSE,
330  lc);
331 
332  return failure == RTI_XCDR_FALSE;
333  }
334 
335  void finish_emheader(char * emheader_position)
336  {
337  RTIXCdrStream_finishV2ParameterHeader(&stream_, emheader_position);
338  }
339 
340  bool align(unsigned int alignment)
341  {
342  return RTIXCdrStream_align(&stream_, (RTIXCdrAlignment) alignment)
343  == RTI_XCDR_TRUE;
344  }
345 
346  bool check_size(length_t size) const
347  {
348  bool result = RTIXCdrStream_checkSize(&stream_, size) == RTI_XCDR_TRUE;
349  return result;
350  }
351 
352  bool need_byte_swap() const
353  {
354  return stream_._needByteSwap != 0;
355  }
356 
357  RTIXCdrStream& c_stream()
358  {
359  return stream_;
360  }
361 
362 
363  // Saves the current position of a stream so it can be restored later on if
364  // needed. This utility has two main uses:
365  // - For Offsets: move the offset to a member, then go back
366  // - For Builders: allow rolling back to the state before starting building
367  // a member, in case of an error or a call to the builder's discard()
368  //
369  // For maintainability we also save the relativeBuffer, but FlatData doesn't
370  // use it.
371  class Memento {
372  public:
373  explicit Memento(Stream& stream) :
374  stream_(stream),
375  original_position_(stream.current_position()),
376  relative_buffer_(stream.c_stream()._relativeBuffer)
377  {
378  }
379 
380  // Restores the saved position unless discard() has been called
381  ~Memento()
382  {
383  restore();
384  }
385 
386  // Restores the saved position unless discard() has been called
387  void restore()
388  {
389  if (original_position_ != NULL) {
390  stream_.current_position(original_position_);
391  stream_.c_stream()._relativeBuffer = relative_buffer_;
392  }
393  }
394 
395  // Call this to no longer restore the original position
396  unsigned char * discard()
397  {
398  unsigned char *pos = original_position_;
399  original_position_ = NULL;
400  return pos;
401  }
402 
403  private:
404  Stream& stream_;
405  unsigned char *original_position_;
406  char *relative_buffer_;
407  };
408 
409 
410 private:
411  RTIXCdrStream stream_;
412 };
413 
414 } } // namespace rti::xcdr
415 
416 #endif // RTI_XCDR_STREAM_HPP_
RTICdrLongLong DDS_LongLong
Defines an extra-long integer data type, equivalent to IDL/CDR long long.
Definition: dds_c.1.0/interface/common.ifc:254
RTICdrUnsignedLongLong DDS_UnsignedLongLong
Defines an unsigned extra-long data type, equivalent to IDL/CDR unsigned long long.
Definition: dds_c.1.0/interface/common.ifc:259
Definition: AggregationBuilders.hpp:17