RTI Connext Traditional C++ API  Version 7.0.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  Stream& operator=(const Stream& other)
208  {
209  stream_ = other.stream_; // shallow assign (see copy constructor)
210  return *this;
211  }
212 
213  bool skip(length_t size)
214  {
215  if (!check_size(size)) {
216  return false;
217  }
218  RTIXCdrStream_increaseCurrentPosition(&stream_, size);
219  return true;
220  }
221 
222  void skip_fast(length_t size)
223  {
224  RTIXCdrStream_increaseCurrentPosition(&stream_, size);
225  }
226 
227  void skip_back(length_t bytes)
228  {
229  RTIXCdrStream_increaseCurrentPosition(
230  &stream_,
231  -static_cast<int>(bytes));
232  }
233 
234  unsigned char * buffer()
235  {
236  return reinterpret_cast<unsigned char*>(stream_._buffer);
237  }
238 
239  const unsigned char * buffer() const
240  {
241  return reinterpret_cast<unsigned char*>(stream_._buffer);
242  }
243 
244  unsigned char * current_position()
245  {
246  return reinterpret_cast<unsigned char*>(
247  RTIXCdrStream_getCurrentPosition(&stream_));
248  }
249 
250  void current_position(unsigned char * pos)
251  {
252  RTIXCdrStream_setCurrentPosition(
253  &stream_,
254  reinterpret_cast<char*>(pos));
255  }
256 
257  length_t used_size() const
258  {
259  return static_cast<length_t>(
260  RTIXCdrStream_getCurrentPosition(&stream_) - stream_._buffer);
261  }
262 
263  length_t remaining_size() const
264  {
265  return total_size() - used_size();
266  }
267 
268  length_t total_size() const
269  {
270  return stream_._bufferLength;
271  }
272 
273  bool needs_byte_swap() const
274  {
275  return stream_._needByteSwap == RTI_XCDR_TRUE;
276  }
277 
278  template <typename T>
279  bool serialize(T value)
280  {
281  return primitive_type_traits<T>::serialize(&stream_, &value);
282  }
283 
284  template <typename T>
285  void serialize_fast(T value)
286  {
287  primitive_type_traits<T>::serialize_fast(&stream_, &value);
288  }
289 
290  template <typename T>
291  bool serialize_no_align(T value)
292  {
293  if (!check_size(sizeof(T))) {
294  return false;
295  }
296  primitive_type_traits<T>::serialize_fast(&stream_, &value);
297  return true;
298  }
299 
300  template <typename T>
301  T deserialize_fast()
302  {
303  T value;
304  primitive_type_traits<T>::deserialize_fast(&stream_, &value);
305  return value;
306  }
307 
308  void serialize_fast(const void *array, length_t bytes)
309  {
310  RTIXCdrStream_serializeNByteFast(&stream_, array, bytes);
311  }
312 
313  char * serialize_dheader()
314  {
315  return RTIXCdrStream_serializeDHeader(&stream_);
316  }
317 
318  bool finish_dheader(char *dheader_position)
319  {
320  return RTIXCdrStream_serializeDHeaderLength(&stream_, dheader_position)
321  == RTI_XCDR_TRUE;
322  }
323 
324  bool serialize_emheader(
325  char*& position,
326  RTIXCdrUnsignedLong parameter_id,
327  RTIXCdrUnsignedLong lc,
328  bool must_understand = false)
329  {
330  RTIXCdrBoolean failure = 0;
331  position = RTIXCdrStream_serializeV2ParameterHeader(
332  &stream_,
333  &failure,
334  parameter_id,
335  must_understand ? RTI_XCDR_TRUE : RTI_XCDR_FALSE,
336  lc);
337 
338  return failure == RTI_XCDR_FALSE;
339  }
340 
341  void finish_emheader(char * emheader_position)
342  {
343  RTIXCdrStream_finishV2ParameterHeader(&stream_, emheader_position);
344  }
345 
346  bool align(unsigned int alignment)
347  {
348  return RTIXCdrStream_align(&stream_, (RTIXCdrAlignment) alignment)
349  == RTI_XCDR_TRUE;
350  }
351 
352  bool check_size(length_t size) const
353  {
354  bool result = RTIXCdrStream_checkSize(&stream_, size) == RTI_XCDR_TRUE;
355  return result;
356  }
357 
358  bool need_byte_swap() const
359  {
360  return stream_._needByteSwap != 0;
361  }
362 
363  RTIXCdrStream& c_stream()
364  {
365  return stream_;
366  }
367 
368 
369  // Saves the current position of a stream so it can be restored later on if
370  // needed. This utility has two main uses:
371  // - For Offsets: move the offset to a member, then go back
372  // - For Builders: allow rolling back to the state before starting building
373  // a member, in case of an error or a call to the builder's discard()
374  //
375  // For maintainability we also save the relativeBuffer, but FlatData doesn't
376  // use it.
377  class Memento {
378  public:
379  explicit Memento(Stream& stream) :
380  stream_(stream),
381  original_position_(stream.current_position()),
382  relative_buffer_(stream.c_stream()._relativeBuffer)
383  {
384  }
385 
386  // Restores the saved position unless discard() has been called
387  ~Memento()
388  {
389  restore();
390  }
391 
392  // Restores the saved position unless discard() has been called
393  void restore()
394  {
395  if (original_position_ != NULL) {
396  stream_.current_position(original_position_);
397  stream_.c_stream()._relativeBuffer = relative_buffer_;
398  }
399  }
400 
401  // Call this to no longer restore the original position
402  unsigned char * discard()
403  {
404  unsigned char *pos = original_position_;
405  original_position_ = NULL;
406  return pos;
407  }
408 
409  private:
410  Stream& stream_;
411  unsigned char *original_position_;
412  char *relative_buffer_;
413  };
414 
415 
416 private:
417  RTIXCdrStream stream_;
418 };
419 
420 } } // namespace rti::xcdr
421 
422 #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