RTI Connext Traditional C++ API Version 7.3.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_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
416private:
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
The RTI namespace.
Definition: AggregationBuilders.hpp:17