RTI Connext Traditional C++ API  Version 6.0.1
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
SequenceIterator.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_SEQUENCEITERATOR_HPP_
12 #define RTI_DDS_FLAT_SEQUENCEITERATOR_HPP_
13 
14 #include <iterator>
15 
16 #include "rti/flat/Offset.hpp"
17 
18 namespace rti { namespace flat {
19 
43 template <typename E, typename OffsetKind>
45 public:
49  typedef std::forward_iterator_tag iterator_category;
50 
54  typedef E value_type;
55 
60 
65 
69  typedef std::ptrdiff_t difference_type;
70 
74  SequenceIterator() : sample_(NULL), current_offset_(0), max_offset_(0)
75  {
76  }
77 
79  rti::flat::SampleBase *sample,
80  offset_t initial_offset,
81  offset_t max_offset)
82  : sample_(sample),
83  current_offset_(initial_offset),
84  max_offset_(max_offset)
85  {
86  RTI_FLAT_ASSERT(sample != NULL, return);
87  }
88 
92  bool is_null() const
93  {
94  return sample_ == NULL;
95  }
96 
106  {
107  return get_impl(OffsetKind());
108  }
109 
114  {
115  return get_impl(OffsetKind());
116  }
117 
132  bool advance()
133  {
134  // Unlike operator++, advance() allows checking for errors when
135  // exceptions are disabled (traditional C++)
136  return advance_impl(OffsetKind());
137  }
138 
148  {
149  bool can_advance_iter = advance_impl(OffsetKind());
150  RTI_FLAT_CHECK_PRECONDITION(can_advance_iter, return *this);
151  return *this;
152  }
153 
163  {
164  SequenceIterator tmp(*this);
165  ++(*this);
166  return tmp;
167  }
168 
172  friend bool operator<(
173  const SequenceIterator & s1,
174  const SequenceIterator & s2)
175  {
176  return s1.get_position() < s2.get_position();
177  }
178 
182  friend bool operator > (
183  const SequenceIterator & s1,
184  const SequenceIterator & s2)
185  {
186  return s1.get_position() > s2.get_position();
187  }
188 
192  friend bool operator <= (
193  const SequenceIterator & s1,
194  const SequenceIterator & s2)
195  {
196  return s1.get_position() <= s2.get_position();
197  }
198 
202  friend bool operator >= (
203  const SequenceIterator & s1,
204  const SequenceIterator & s2)
205  {
206  return s1.get_position() >= s2.get_position();
207  }
208 
212  friend bool operator == (
213  const SequenceIterator & s1,
214  const SequenceIterator & s2)
215  {
216  return s1.get_position() == s2.get_position();
217  }
218 
222  friend bool operator != (
223  const SequenceIterator & s1,
224  const SequenceIterator & s2)
225  {
226  return !(s1 == s2);
227  }
228 
229  unsigned char * get_position() const
230  {
231  if (is_null()) {
232  return NULL;
233  } else {
234  return sample_->get_buffer() + current_offset_;
235  }
236  }
237 
238 private:
239  E get_impl(variable_size_type_tag_t) const
240  {
241  if (is_null()) {
242  return E();
243  }
244 
245  // The iterator points to the end of the previous element. If elements
246  // need padding, we have to add it here (required alignment is 4 because
247  // mutable types (variable_size_type_tag_t) are always aligned to 4)
248  offset_t offset = RTIXCdrAlignment_alignSizeUp(current_offset_, 4);
249 
250  if (offset >= max_offset_) {
251  return E();
252  }
253 
254  // Calculate the size of the current element; if E is a struct type,
255  // this will be quick (just deserialize the DHeader); if we're itearating
256  // over an array of sequences (E is a sequence), this will require
257  // skipping over the current sequence.
258  offset_t size = E::Helper::calculate_serialized_size(
259  sample_,
260  offset,
261  max_offset_);
262  // size 0 indicates an error; a variable-size type E cannot have size
263  // zero because it will always have a header (DHeader for mutable structs,
264  // length for sequences)
265  if (size == 0) {
266  return E();
267  }
268 
269  return E(sample_, offset, size);
270  }
271 
272  E get_impl(fixed_size_type_tag_t) const
273  {
274  if (is_null()) {
275  return E();
276  }
277 
278  // The iterator points to the end of the previous element. If elements
279  // need padding, we have to add it here.
280  offset_t offset = RTIXCdrAlignment_alignSizeUp(
281  current_offset_,
282  E::required_alignment);
283  if (offset >= max_offset_) {
284  return E();
285  }
286 
287  return E(sample_, offset);
288  }
289 
290  bool advance_impl(variable_size_type_tag_t)
291  {
292  if (is_null()) {
293  return false;
294  }
295 
296  current_offset_ = RTIXCdrAlignment_alignSizeUp(current_offset_, 4);
297  offset_t size = E::Helper::calculate_serialized_size(
298  sample_, // beginning of the buffer
299  current_offset_, // absolute offset to the current element
300  max_offset_); // maximum offset in the list
301  if (size == 0) {
302  return false;
303  }
304 
305  current_offset_ += size;
306 
307  if (current_offset_ > max_offset_) {
308  current_offset_ = max_offset_;
309  return false;
310  }
311 
312  return true;
313  }
314 
315  bool advance_impl(fixed_size_type_tag_t)
316  {
317  if (is_null()) {
318  return false;
319  }
320 
321  // The iterator points to the end of the previous element. If elements
322  // need padding, we have to add it here. We do that to keep the end()
323  // iterator consistent, becuase the last element may not need padding.
324  current_offset_ = RTIXCdrAlignment_alignSizeUp(
325  current_offset_,
326  E::required_alignment);
327  current_offset_ += E::serialized_size(0);
328 
329  if (current_offset_ > max_offset_) {
330  current_offset_ = max_offset_;
331  return false;
332  }
333 
334  return true;
335  }
336 
337  rti::flat::SampleBase *sample_;
338  offset_t current_offset_;
339  offset_t max_offset_;
340 };
341 
342 } }
343 
344 #endif // RTI_DDS_FLAT_SEQUENCEITERATOR_HPP_
345 

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