RTI Connext Traditional C++ API  Version 6.0.1
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
AggregationBuilders.hpp
1 /*
2 (c) Copyright, Real-Time Innovations, 2018.
3 All rights reserved.
4 
5 No duplications, whole or partial, manual or electronic, may be made
6 without express written permission. Any such copies, or
7 revisions thereof, must display this notice unaltered.
8 This code contains trade secrets of Real-Time Innovations, Inc.
9 */
10 
11 #ifndef RTI_DDS_FLAT_AGGREGATIONBUILDERS_HPP_
12 #define RTI_DDS_FLAT_AGGREGATIONBUILDERS_HPP_
13 
14 #include "rti/flat/BuilderHelper.hpp"
15 #include "rti/flat/Builder.hpp"
16 
17 namespace rti { namespace flat {
18 
19 /*
20  * Provides the common functionality for builders of aggregated types
21  *
22  * Extends and specializes AbstractBuilder to add or override the functionality
23  * required to build an aggregated type:
24  *
25  * - Add or build members, prepending the member header
26  * - Add dheader at the beginning
27  * - Add parameter-list-end header at the end
28  */
38 protected:
40  dheader_position_(NULL),
41  emheader_position_(NULL)
42  {
43  }
44 
45  // Create a new top-level builder
47  unsigned char *initial_buffer,
48  offset_t size,
49  bool initialize_members) :
50  AbstractBuilder(initial_buffer, size, initialize_members),
51  dheader_position_(NULL),
52  emheader_position_(NULL)
53  {
54  dheader_position_ = stream().serialize_dheader();
55  if (dheader_position_ == NULL) {
56  RTI_FLAT_BUILDER_OUT_OF_RESOURCES_ERROR(invalidate());
57  }
58  }
59 
60 public:
61  // For internal use and testing
62  //
63  // Modifies the encapsulation set in the constructor with a custom value.
64  // This function can only be called after the construction of a non-nested
65  // Builder, before any member is built or added.
66  //
67  void set_encapsulation_impl(RTIXCdrEncapsulationId encapsulation_id)
68  {
69  // Only a top-level Builder can change the encapsulation
70  RTI_FLAT_CHECK_PRECONDITION(!is_nested(), return);
71 
72  char *current_position = (char *) owned_stream_.current_position();
73  // This operation is only valid right after construction, when no
74  // member has been added yet
75  RTI_FLAT_CHECK_PRECONDITION(
76  current_position == dheader_position_ + RTI_XCDR_DHEADER_SIZE,
77  return);
78 
79  owned_stream_.skip_back(
80  RTI_XCDR_DHEADER_SIZE + RTI_XCDR_ENCAPSULATION_HEADER_SIZE);
81 
82  if (!RTIXCdrFlatSample_initializeEncapsulationAndStream(
83  (char *) owned_stream_.buffer(),
84  &owned_stream_.c_stream(),
85  encapsulation_id,
86  owned_stream_.total_size())) {
87  RTI_FLAT_BUILDER_OUT_OF_RESOURCES_ERROR(return);
88  }
89 
90  stream().serialize_dheader();
91  }
92 
93 protected:
94 
95 #if defined(RTI_FLAT_DATA_CXX11_RVALUE_REFERENCES)
96  AggregationBuilder(AggregationBuilder&& other) = default;
97 
98  AggregationBuilder& operator=(AggregationBuilder&& other)
99  {
100  if (this == &other) {
101  return *this;
102  }
103 
104  finish_untyped_impl();
105 
106  AbstractBuilder::operator=(static_cast<AbstractBuilder&&>(other));
107 
108  dheader_position_ = other.dheader_position_;
109  emheader_position_ = other.emheader_position_;
110 
111  return *this;
112  }
113 #else
114 public:
115  // Enable the safe-move-constructor idiom without C++11 move constructors
116  struct UntypedAggregationBuilderMoveProxy : AbstractBuilderMoveProxy {
117  char * dheader_position_;
118  char * emheader_position_;
119  };
120 
121  operator UntypedAggregationBuilderMoveProxy () throw() // move-constructor idiom
122  {
123  UntypedAggregationBuilderMoveProxy other;
124  move_to(other);
125  return other;
126  }
127 
128 protected:
129  void move_from(UntypedAggregationBuilderMoveProxy& other)
130  {
131  AbstractBuilder::move_from(other);
132  dheader_position_ = other.dheader_position_;
133  emheader_position_ = other.emheader_position_;
134  }
135 
136  void move_to(UntypedAggregationBuilderMoveProxy& other)
137  {
138  AbstractBuilder::move_to(other);
139  other.dheader_position_ = dheader_position_;
140  other.emheader_position_ = emheader_position_;
141  }
142 #endif
143 
144 protected:
145  virtual ~AggregationBuilder()
146  {
147  // AggregationBuilder::finish_untyped_impl() is specialized
148  // with respect to AbstractBuilder::finish_untyped_impl()
149  finish_untyped_impl();
150  }
151 
152  template <typename T>
153  bool add_primitive_member(member_id_t id, T value)
154  {
155  RTI_FLAT_BUILDER_CHECK_VALID(return false);
156 
157  rti::xcdr::Stream::Memento stream_memento(stream());
158 
159  if (!begin_emheader(id, detail::primitive_lc_code<T>::value)) {
160  RTI_FLAT_BUILDER_OUT_OF_RESOURCES_ERROR(return false);
161  }
162  // no need to call finish_emheader()
163 
164  if (!stream().serialize_no_align(value)) {
165  RTI_FLAT_BUILDER_OUT_OF_RESOURCES_ERROR(return false);
166  }
167 
168  stream_memento.discard(); // success: do not restore the current position
169  return true;
170  }
171 
172  template <typename OffsetType>
173  OffsetType add_member(member_id_t id)
174  {
175  RTI_FLAT_BUILDER_CHECK_VALID(return OffsetType());
176 
177  // save state in case of error
178  rti::xcdr::Stream::Memento stream_memento(stream());
179  return add_member<OffsetType>(id, stream_memento);
180  }
181 
182  template <typename OffsetType>
183  OffsetType add_member(
184  member_id_t id,
185  rti::xcdr::Stream::Memento& stream_memento)
186  {
187  // EMHeader with LC = 4; any fixed-size non-primitive member will have
188  // LC = 4 since they don't encode a length
189  if (!begin_emheader(id, 4)) {
190  return OffsetType();
191  }
192 
193  OffsetType result = AbstractBuilder::add_element<OffsetType>();
194  finish_emheader();
195 
196  stream_memento.discard(); // success - do not restore the previous state
197  return result;
198  }
199 
200  template <typename NestedBuilder>
201  NestedBuilder build_member(member_id_t id)
202  {
203  RTI_FLAT_BUILDER_CHECK_VALID(return NestedBuilder());
204 
205  // save state in case of error
206  rti::xcdr::Stream::Memento stream_memento(stream());
207  return build_member<NestedBuilder>(id, stream_memento);
208  }
209 
210  template <typename NestedBuilder>
211  NestedBuilder build_member(
212  member_id_t id,
213  rti::xcdr::Stream::Memento& stream_memento)
214  {
215  if (!begin_emheader(id, detail::lc_code<NestedBuilder>::value)) {
216  return NestedBuilder();
217  }
218 
219  return AbstractBuilder::build_element_no_align<NestedBuilder>(
220  stream_memento);
221  }
222 
223  unsigned char* finish_sample_impl()
224  {
225  RTI_FLAT_BUILDER_CHECK_VALID(return NULL);
226  RTI_FLAT_BUILDER_CHECK_NOT_BOUND(return NULL);
227  RTI_FLAT_BUILDER_CHECK_CAN_FINISH_SAMPLE(return NULL);
228 
229  if (!stream().finish_dheader(dheader_position_)) {
230  RTI_FLAT_BUILDER_OUT_OF_RESOURCES_ERROR(return NULL);
231  }
232 
233  unsigned char *return_sample = stream().buffer();
234  invalidate();
235 
236  return return_sample;
237  }
238 
239  // Same as finish_impl() but it doesn't throw exceptions or return an Offset
240  void finish_untyped_impl()
241  {
242  if (is_valid() && is_nested()) {
243  stream().finish_dheader(dheader_position_);
244  AbstractBuilder::finish_untyped_impl();
245  }
246  }
247 
248  template <typename OffsetType>
249  OffsetType finish_impl()
250  {
251  RTI_FLAT_BUILDER_CHECK_VALID(return OffsetType());
252  RTI_FLAT_BUILDER_CHECK_CAN_FINISH(return OffsetType());
253 
254  stream().finish_dheader(dheader_position_);
255  return AbstractBuilder::finish_impl<OffsetType>();
256  }
257 
258 public:
259  // For internal use; need to use rti::flat::discard_sample(writer, builder)
260  unsigned char * discard_sample_impl()
261  {
262  RTI_FLAT_BUILDER_CHECK_VALID(return NULL);
263  RTI_FLAT_BUILDER_CHECK_NOT_BOUND(return NULL);
264  RTI_FLAT_BUILDER_CHECK_CAN_FINISH_SAMPLE(return NULL);
265 
266  unsigned char *buffer = this->buffer();
267  invalidate();
268  return buffer;
269  }
270 
271 private:
272  void finish_member() // override noexcept
273  {
274  if (!is_valid()) {
275  return;
276  }
277 
278  finish_emheader();
279  AbstractBuilder::finish_member();
280  }
281 
282 private:
283 
284  bool begin_emheader(member_id_t id, RTIXCdrUnsignedLong lc)
285  {
286  RTI_FLAT_BUILDER_CHECK_NOT_BOUND(return false);
287 
288  if (!stream().serialize_emheader(emheader_position_, id, lc)) {
289  RTI_FLAT_BUILDER_OUT_OF_RESOURCES_ERROR(return false);
290  }
291 
292  return true;
293  }
294 
295  void finish_emheader() // noexcept
296  {
297  if (emheader_position_ != NULL) {
298  stream().finish_emheader(emheader_position_);
299  emheader_position_ = NULL;
300  }
301  }
302 
303 protected:
304  // Create a nested builder
305  AggregationBuilder(nested_tag_t, AbstractBuilder& parent, unsigned int alignment)
306  : AbstractBuilder(nested_tag_t(), parent, alignment),
307  dheader_position_(NULL),
308  emheader_position_(NULL)
309  {
310  dheader_position_ = stream().serialize_dheader();
311  if (dheader_position_ == NULL) {
312  RTI_FLAT_BUILDER_OUT_OF_RESOURCES_ERROR(invalidate());
313  }
314  }
315 
316 private:
317  char * dheader_position_;
318  char * emheader_position_;
319 };
320 
321 // Specializes an AggregationBuilder to enforce that only one member can
322 // be set at a time
332 template <typename Discriminator>
334 protected:
335  UnionBuilder()
336  {
337  }
338 
339  // Create a new top-level builder
340  UnionBuilder(
341  unsigned char *initial_buffer,
342  offset_t size,
343  bool initialize_members) :
344  AggregationBuilder(initial_buffer, size, initialize_members)
345  {
346  }
347 
348  template <typename T>
349  bool add_primitive_member(member_id_t id, Discriminator disc, T value)
350  {
351  RTI_FLAT_BUILDER_CHECK_VALID(return false);
352 
353  // Always start at the beginning and override any member or discriminator
354  // that may have been set
355  move_to_discriminator();
356  rti::xcdr::Stream::Memento stream_memento(stream());
357 
358  if (!add_discriminator(disc)) {
359  return false;
360  }
361 
362  if (!AggregationBuilder::add_primitive_member(id, value)) {
363  return false;
364  }
365 
366  stream_memento.discard(); // success: do not restore the current position
367  return true;
368  }
369 
370  template <typename OffsetType>
371  OffsetType add_member(member_id_t id, Discriminator disc)
372  {
373  RTI_FLAT_BUILDER_CHECK_VALID(return OffsetType());
374 
375  move_to_discriminator();
376  rti::xcdr::Stream::Memento stream_memento(stream());
377  if (!add_discriminator(disc)) {
378  RTI_FLAT_BUILDER_OUT_OF_RESOURCES_ERROR(return OffsetType());
379  }
380 
381  return AggregationBuilder::add_member<OffsetType>(id, stream_memento);
382  }
383 
384  template <typename NestedBuilder>
385  NestedBuilder build_member(member_id_t id, Discriminator disc)
386  {
387  RTI_FLAT_BUILDER_CHECK_VALID(return NestedBuilder());
388 
389  move_to_discriminator();
390  rti::xcdr::Stream::Memento stream_memento(stream());
391  add_discriminator(disc);
392 
393  return AggregationBuilder::build_member<NestedBuilder>(id, stream_memento);
394  }
395 
396  // Create a nested builder
397  UnionBuilder(nested_tag_t, AbstractBuilder& parent, unsigned int alignment)
398  : AggregationBuilder(nested_tag_t(), parent, alignment)
399  {
400  }
401 
402 private:
403  void move_to_discriminator()
404  {
405  stream().current_position(begin_position() + RTI_XCDR_DHEADER_SIZE);
406  }
407 
408  bool add_discriminator(Discriminator disc)
409  {
410  return AggregationBuilder::add_primitive_member(0, disc);
411  }
412 };
413 
414 
415 } }
416 
417 #endif // RTI_DDS_FLAT_AGGREGATIONBUILDERS_HPP_
418 

RTI Connext Traditional C++ API Version 6.0.1 Copyright © Sat Nov 23 2019 Real-Time Innovations, Inc