RTI Connext Traditional C++ API  Version 6.0.0
 All Classes Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
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 #if !defined(RTI_AVOID_FIXED_WIDTH_INTEGERS)
101 // Base case is empty: there are specializations for each possible primitive;
102 // other specializations may be added in the C++ DDS API that includes Flat Data
103 // (namely dds_cpp.2.0, which specializes these traits for safe_enums)
104 template <typename T>
105 struct primitive_type_traits {};
106 #else
107 // Base case handles T as an 4-byte integer (this is necessary for traditional
108 // C++ enums)
109 template <typename T>
110 struct primitive_type_traits {
111  RTI_XCDR_SPECIALIZE_PRIMITIVE_TYPE_TRAITS_BODY(T, RTIXCdr4Byte, serialize4)
112 };
113 #endif
114 
115 RTI_XCDR_SPECIALIZE_PRIMITIVE_TYPE_TRAITS_NO_ALIGN_PARAM(\
116  char, RTIXCdr1Byte, serialize1);
117 
118 // The API can work with fixed-width integers (dds_cpp.2.0) or
119 // RTI-defined integers (dds_cpp.1.0). We need to make this distinction because
120 // on some platforms these types may not be exactly the same as far as template
121 // resolution. That is, compilers may or may not pick the template
122 // specialization for int32_t for an instantiation with int.
123 //
124 // If we define only one (e.g. int32_t) some compilers won't find a suitable
125 // definition for int. If we define both, some compilers will find duplicate
126 // definitions for int/int32_t.
127 #if !defined(RTI_AVOID_FIXED_WIDTH_INTEGERS)
128 RTI_XCDR_SPECIALIZE_PRIMITIVE_TYPE_TRAITS_NO_ALIGN_PARAM(\
129  uint8_t, RTIXCdr1Byte, serialize1);
130 
131 RTI_XCDR_SPECIALIZE_PRIMITIVE_TYPE_TRAITS(\
132  int16_t, RTIXCdr2Byte, serialize2);
133 RTI_XCDR_SPECIALIZE_PRIMITIVE_TYPE_TRAITS(\
134  uint16_t, RTIXCdr2Byte, serialize2);
135 
136 RTI_XCDR_SPECIALIZE_PRIMITIVE_TYPE_TRAITS(\
137  int32_t, RTIXCdr4Byte, serialize4);
138 RTI_XCDR_SPECIALIZE_PRIMITIVE_TYPE_TRAITS(\
139  uint32_t, RTIXCdr4Byte, serialize4);
140 
141 typedef uint32_t length_t;
142 #else
143 RTI_XCDR_SPECIALIZE_PRIMITIVE_TYPE_TRAITS_NO_ALIGN_PARAM(\
144  unsigned char, RTIXCdr1Byte, serialize1);
145 
146 RTI_XCDR_SPECIALIZE_PRIMITIVE_TYPE_TRAITS(\
147  short, RTIXCdr2Byte, serialize2);
148 RTI_XCDR_SPECIALIZE_PRIMITIVE_TYPE_TRAITS(\
149  unsigned short, RTIXCdr2Byte, serialize2);
150 
151 // int and unsigned int, as well as enum are handled by the general case
152 
153 typedef unsigned int length_t;
154 #endif
155 
156 RTI_XCDR_SPECIALIZE_PRIMITIVE_TYPE_TRAITS(\
157  float, RTIXCdr4Byte, serialize4);
158 
159 RTI_XCDR_SPECIALIZE_PRIMITIVE_TYPE_TRAITS_W_ALIGNMENT_PARAM(\
160  DDS_LongLong, RTIXCdr8Byte, serialize8, 4);
161 
162 RTI_XCDR_SPECIALIZE_PRIMITIVE_TYPE_TRAITS_W_ALIGNMENT_PARAM(\
163  DDS_UnsignedLongLong, RTIXCdr8Byte, serialize8, 4);
164 RTI_XCDR_SPECIALIZE_PRIMITIVE_TYPE_TRAITS_W_ALIGNMENT_PARAM(\
165  double, RTIXCdr8Byte, serialize8, 4);
166 
167 // RTI_XCDR_SPECIALIZE_PRIMITIVE_TYPE_TRAITS(
168 // rti::core::LongDouble, RTI_CDR_LONG_DOUBLE_TYPE, RTIXCdr16Byte, serialize16Byte);
169 
170 template <typename T>
171 void serialize_fast(RTIXCdrStream& stream, const T& value)
172 {
173  primitive_type_traits<T>::serialize_fast(&stream, &value);
174 }
175 
176 template <typename T>
177 void deserialize_fast(RTIXCdrStream& stream, T& value)
178 {
179  primitive_type_traits<T>::deserialize_fast(&stream, &value);
180 }
181 
182 class Stream {
183 public:
184  Stream()
185  {
186  RTIXCdrStream_set(&stream_, NULL, 0);
187  }
188 
189  explicit Stream(const RTIXCdrStream& c_stream)
190  {
191  stream_ = c_stream; // shallow assign
192  }
193 
194  // Creates a new stream that shares the same buffer and current position
195  // as another Stream
196  Stream(const Stream& other)
197  {
198  stream_ = other.stream_; // shallow assign
199  }
200 
201  // Creates a new Stream from an existing already-initialized buffer, whose
202  // encapsulation has already been set
203  Stream(
204  unsigned char *buffer,
205  length_t size,
206  length_t offset)
207  {
208  RTIXCdrFlatData_initializeStream(
209  &stream_,
210  buffer,
211  offset,
212  size);
213  }
214 
215  bool skip(length_t size)
216  {
217  if (!check_size(size)) {
218  return false;
219  }
220  RTIXCdrStream_increaseCurrentPosition(&stream_, size);
221  return true;
222  }
223 
224  void skip_fast(length_t size)
225  {
226  RTIXCdrStream_increaseCurrentPosition(&stream_, size);
227  }
228 
229  void skip_back(length_t bytes)
230  {
231  RTIXCdrStream_increaseCurrentPosition(
232  &stream_,
233  -static_cast<int>(bytes));
234  }
235 
236  unsigned char * buffer()
237  {
238  return reinterpret_cast<unsigned char*>(stream_._buffer);
239  }
240 
241  const unsigned char * buffer() const
242  {
243  return reinterpret_cast<unsigned char*>(stream_._buffer);
244  }
245 
246  unsigned char * current_position()
247  {
248  return reinterpret_cast<unsigned char*>(
249  RTIXCdrStream_getCurrentPosition(&stream_));
250  }
251 
252  void current_position(unsigned char * pos)
253  {
254  RTIXCdrStream_setCurrentPosition(
255  &stream_,
256  reinterpret_cast<char*>(pos));
257  }
258 
259  length_t used_size() const
260  {
261  return static_cast<length_t>(
262  RTIXCdrStream_getCurrentPosition(&stream_) - stream_._buffer);
263  }
264 
265  length_t remaining_size() const
266  {
267  return total_size() - used_size();
268  }
269 
270  length_t total_size() const
271  {
272  return stream_._bufferLength;
273  }
274 
275  bool needs_byte_swap() const
276  {
277  return stream_._needByteSwap == RTI_XCDR_TRUE;
278  }
279 
280  template <typename T>
281  bool serialize(T value)
282  {
283  return primitive_type_traits<T>::serialize(&stream_, &value);
284  }
285 
286  template <typename T>
287  void serialize_fast(T value)
288  {
289  primitive_type_traits<T>::serialize_fast(&stream_, &value);
290  }
291 
292  template <typename T>
293  bool serialize_no_align(T value)
294  {
295  if (!check_size(sizeof(T))) {
296  return false;
297  }
298  primitive_type_traits<T>::serialize_fast(&stream_, &value);
299  return true;
300  }
301 
302  template <typename T>
303  T deserialize_fast()
304  {
305  T value;
306  primitive_type_traits<T>::deserialize_fast(&stream_, &value);
307  return value;
308  }
309 
310  void serialize_fast(const void *array, length_t bytes)
311  {
312  RTIXCdrStream_serializeNByteFast(&stream_, array, bytes);
313  }
314 
315  char * serialize_dheader()
316  {
317  return RTIXCdrStream_serializeDHeader(&stream_);
318  }
319 
320  bool finish_dheader(char *dheader_position)
321  {
322  return RTIXCdrStream_serializeDHeaderLength(&stream_, dheader_position);
323  }
324 
325  bool serialize_emheader(
326  char*& position,
327  RTIXCdrUnsignedLong parameter_id,
328  RTIXCdrUnsignedLong lc,
329  bool must_understand = false)
330  {
331  RTIXCdrBoolean failure = 0;
332  position = RTIXCdrStream_serializeV2ParameterHeader(
333  &stream_,
334  &failure,
335  parameter_id,
336  must_understand ? RTI_XCDR_TRUE : RTI_XCDR_FALSE,
337  lc);
338 
339  return !failure;
340  }
341 
342  void finish_emheader(char * emheader_position)
343  {
344  RTIXCdrStream_finishV2ParameterHeader(&stream_, emheader_position);
345  }
346 
347  bool align(unsigned int alignment)
348  {
349  return RTIXCdrStream_align(&stream_, (RTIXCdrAlignment) alignment);
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  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_

RTI Connext Traditional C++ API Version 6.0.0 Copyright © Sun Mar 3 2019 Real-Time Innovations, Inc