RTI Connext Traditional C++ API Version 7.6.0
Stream.hpp
1/* $Id$
2
3(c) Copyright, Real-Time Innovations, 2018.
4All rights reserved.
5
6No duplications, whole or partial, manual or electronic, may be made
7without express written permission. Any such copies, or
8revisions thereof, must display this notice unaltered.
9This 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
18namespace 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)\
46template <>\
47struct primitive_type_traits<TYPE> {\
48RTI_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)\
56template <>\
57struct 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)\
80template <>\
81struct 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)
102template <typename T>
103struct primitive_type_traits {
104 RTI_XCDR_SPECIALIZE_PRIMITIVE_TYPE_TRAITS_BODY(T, RTIXCdr4Byte, serialize4)
105};
106
107RTI_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)
120RTI_XCDR_SPECIALIZE_PRIMITIVE_TYPE_TRAITS_NO_ALIGN_PARAM(\
121 uint8_t, RTIXCdr1Byte, serialize1);
122
123RTI_XCDR_SPECIALIZE_PRIMITIVE_TYPE_TRAITS(\
124 int16_t, RTIXCdr2Byte, serialize2);
125RTI_XCDR_SPECIALIZE_PRIMITIVE_TYPE_TRAITS(\
126 uint16_t, RTIXCdr2Byte, serialize2);
127
128RTI_XCDR_SPECIALIZE_PRIMITIVE_TYPE_TRAITS(\
129 int32_t, RTIXCdr4Byte, serialize4);
130RTI_XCDR_SPECIALIZE_PRIMITIVE_TYPE_TRAITS(\
131 uint32_t, RTIXCdr4Byte, serialize4);
132
133typedef uint32_t length_t;
134#else
135RTI_XCDR_SPECIALIZE_PRIMITIVE_TYPE_TRAITS_NO_ALIGN_PARAM(\
136 unsigned char, RTIXCdr1Byte, serialize1);
137
138RTI_XCDR_SPECIALIZE_PRIMITIVE_TYPE_TRAITS(\
139 short, RTIXCdr2Byte, serialize2);
140RTI_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
145typedef unsigned int length_t;
146#endif
147
148RTI_XCDR_SPECIALIZE_PRIMITIVE_TYPE_TRAITS(\
149 float, RTIXCdr4Byte, serialize4);
150
151RTI_XCDR_SPECIALIZE_PRIMITIVE_TYPE_TRAITS_W_ALIGNMENT_PARAM(\
152 DDS_LongLong, RTIXCdr8Byte, serialize8, 4);
153
154RTI_XCDR_SPECIALIZE_PRIMITIVE_TYPE_TRAITS_W_ALIGNMENT_PARAM(\
155 DDS_UnsignedLongLong, RTIXCdr8Byte, serialize8, 4);
156RTI_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
162template <typename T>
163void serialize_fast(RTIXCdrStream& stream, const T& value)
164{
165 primitive_type_traits<T>::serialize_fast(&stream, &value);
166}
167
168template <typename T>
169void deserialize_fast(RTIXCdrStream& stream, T& value)
170{
171 primitive_type_traits<T>::deserialize_fast(&stream, &value);
172}
173
174class Stream {
175public:
176 Stream()
177 {
178 RTIXCdrStream_init(&stream_);
179 RTIXCdrStream_set(&stream_, NULL, 0);
180
181 stream_._tmpRelativeBuffer = NULL;
182 stream_._needByteSwap = 0;
183 stream_._endian = stream_._nativeEndian;
184 stream_._encapsulationKind = 0;
185 stream_._encapsulationOptions = 0;
186 }
187
188 explicit Stream(const RTIXCdrStream& c_stream)
189 {
190 stream_ = c_stream; // shallow assign
191 }
192
193 // Creates a new stream that shares the same buffer and current position
194 // as another Stream
195 Stream(const Stream& other)
196 {
197 stream_ = other.stream_; // shallow assign
198 }
199
200 // Creates a new Stream from an existing already-initialized buffer, whose
201 // encapsulation has already been set
202 Stream(
203 unsigned char *buffer,
204 length_t size,
205 length_t offset)
206 {
207 RTIXCdrFlatData_initializeStream(
208 &stream_,
209 buffer,
210 offset,
211 size);
212 }
213
214 Stream& operator=(const Stream& other)
215 {
216 stream_ = other.stream_; // shallow assign (see copy constructor)
217 return *this;
218 }
219
220 bool skip(length_t size)
221 {
222 if (!check_size(size)) {
223 return false;
224 }
225 RTIXCdrStream_increaseCurrentPosition(&stream_, size);
226 return true;
227 }
228
229 void skip_fast(length_t size)
230 {
231 RTIXCdrStream_increaseCurrentPosition(&stream_, size);
232 }
233
234 void skip_back(length_t bytes)
235 {
236 RTIXCdrStream_increaseCurrentPosition(
237 &stream_,
238 -static_cast<int>(bytes));
239 }
240
241 unsigned char * buffer()
242 {
243 return reinterpret_cast<unsigned char*>(stream_._buffer);
244 }
245
246 const unsigned char * buffer() const
247 {
248 return reinterpret_cast<unsigned char*>(stream_._buffer);
249 }
250
251 unsigned char * current_position()
252 {
253 return reinterpret_cast<unsigned char*>(
254 RTIXCdrStream_getCurrentPosition(&stream_));
255 }
256
257 void current_position(unsigned char * pos)
258 {
259 RTIXCdrStream_setCurrentPosition(
260 &stream_,
261 reinterpret_cast<char*>(pos));
262 }
263
264 length_t used_size() const
265 {
266 return static_cast<length_t>(
267 RTIXCdrStream_getCurrentPosition(&stream_) - stream_._buffer);
268 }
269
270 length_t remaining_size() const
271 {
272 return total_size() - used_size();
273 }
274
275 length_t total_size() const
276 {
277 return stream_._bufferLength;
278 }
279
280 bool needs_byte_swap() const
281 {
282 return stream_._needByteSwap == RTI_XCDR_TRUE;
283 }
284
285 template <typename T>
286 bool serialize(T value)
287 {
288 return primitive_type_traits<T>::serialize(&stream_, &value);
289 }
290
291 template <typename T>
292 void serialize_fast(T value)
293 {
294 primitive_type_traits<T>::serialize_fast(&stream_, &value);
295 }
296
297 template <typename T>
298 bool serialize_no_align(T value)
299 {
300 if (!check_size(sizeof(T))) {
301 return false;
302 }
303 primitive_type_traits<T>::serialize_fast(&stream_, &value);
304 return true;
305 }
306
307 template <typename T>
308 T deserialize_fast()
309 {
310 T value;
311 primitive_type_traits<T>::deserialize_fast(&stream_, &value);
312 return value;
313 }
314
315 void serialize_fast(const void *array, length_t bytes)
316 {
317 RTIXCdrStream_serializeNByteFast(&stream_, array, bytes);
318 }
319
320 char * serialize_dheader()
321 {
322 return RTIXCdrStream_serializeDHeader(&stream_);
323 }
324
325 bool finish_dheader(char *dheader_position)
326 {
327 return RTIXCdrStream_serializeDHeaderLength(&stream_, dheader_position)
328 == RTI_XCDR_TRUE;
329 }
330
331 bool serialize_emheader(
332 char*& position,
333 RTIXCdrUnsignedLong parameter_id,
334 RTIXCdrUnsignedLong lc,
335 bool must_understand = false)
336 {
337 RTIXCdrBoolean failure = 0;
338 position = RTIXCdrStream_serializeV2ParameterHeader(
339 &stream_,
340 &failure,
341 parameter_id,
342 must_understand ? RTI_XCDR_TRUE : RTI_XCDR_FALSE,
343 lc);
344
345 return failure == RTI_XCDR_FALSE;
346 }
347
348 void finish_emheader(char * emheader_position)
349 {
350 RTIXCdrStream_finishV2ParameterHeader(&stream_, emheader_position);
351 }
352
353 bool align(unsigned int alignment)
354 {
355 return RTIXCdrStream_align(&stream_, (RTIXCdrAlignment) alignment)
356 == RTI_XCDR_TRUE;
357 }
358
359 bool check_size(length_t size) const
360 {
361 bool result = RTIXCdrStream_checkSize(&stream_, size) == RTI_XCDR_TRUE;
362 return result;
363 }
364
365 bool need_byte_swap() const
366 {
367 return stream_._needByteSwap != 0;
368 }
369
370 RTIXCdrStream& c_stream()
371 {
372 return stream_;
373 }
374
375
376 // Saves the current position of a stream so it can be restored later on if
377 // needed. This utility has two main uses:
378 // - For Offsets: move the offset to a member, then go back
379 // - For Builders: allow rolling back to the state before starting building
380 // a member, in case of an error or a call to the builder's discard()
381 //
382 // For maintainability we also save the relativeBuffer, but FlatData doesn't
383 // use it.
384 class Memento {
385 public:
386 explicit Memento(Stream& stream) :
387 stream_(stream),
388 original_position_(stream.current_position()),
389 relative_buffer_(stream.c_stream()._relativeBuffer)
390 {
391 }
392
393 // Restores the saved position unless discard() has been called
394 ~Memento()
395 {
396 restore();
397 }
398
399 // Restores the saved position unless discard() has been called
400 void restore()
401 {
402 if (original_position_ != NULL) {
403 stream_.current_position(original_position_);
404 stream_.c_stream()._relativeBuffer = relative_buffer_;
405 }
406 }
407
408 // Call this to no longer restore the original position
409 unsigned char * discard()
410 {
411 unsigned char *pos = original_position_;
412 original_position_ = NULL;
413 return pos;
414 }
415
416 private:
417 Stream& stream_;
418 unsigned char *original_position_;
419 char *relative_buffer_;
420 };
421
422
423private:
424 RTIXCdrStream stream_;
425};
426
427} } // namespace rti::xcdr
428
429#endif // RTI_XCDR_STREAM_HPP_
RTICdrLongLong DDS_LongLong
Defines an extra-long integer data type, equivalent to IDL/CDR long long.
Definition: common.ifc:254
RTICdrUnsignedLongLong DDS_UnsignedLongLong
Defines an unsigned extra-long data type, equivalent to IDL/CDR unsigned long long.
Definition: common.ifc:259
The RTI namespace.
Definition: AggregationBuilders.hpp:17