RTI Connext Traditional C++ API Version 7.3.0
SequenceIterator.hpp
1/*
2(c) Copyright, Real-Time Innovations, 2018.
3All rights reserved.
4
5No duplications, whole or partial, manual or electronic, may be made
6without express written permission. Any such copies, or
7revisions thereof, must display this notice unaltered.
8This 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
18namespace rti { namespace flat {
19
43template <typename E, typename OffsetKind>
45public:
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
238private:
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
Iterator for collections of Offsets.
Definition: SequenceIterator.hpp:44
friend bool operator==(const SequenceIterator &s1, const SequenceIterator &s2)
Compares two iterators.
Definition: SequenceIterator.hpp:212
SequenceIterator operator++(int)
Advances to the next element.
Definition: SequenceIterator.hpp:162
friend bool operator<(const SequenceIterator &s1, const SequenceIterator &s2)
Compares two iterators.
Definition: SequenceIterator.hpp:172
value_type pointer
The pointer type is the same as the value type, an Offset.
Definition: SequenceIterator.hpp:64
SequenceIterator()
Constructs an invalid iterator.
Definition: SequenceIterator.hpp:74
friend bool operator>=(const SequenceIterator &s1, const SequenceIterator &s2)
Compares two iterators.
Definition: SequenceIterator.hpp:202
std::ptrdiff_t difference_type
The difference type.
Definition: SequenceIterator.hpp:69
value_type operator*() const
Returns the Offset of the current element.
Definition: SequenceIterator.hpp:105
friend bool operator>(const SequenceIterator &s1, const SequenceIterator &s2)
Compares two iterators.
Definition: SequenceIterator.hpp:182
E value_type
The element type.
Definition: SequenceIterator.hpp:54
bool is_null() const
Returns whether the iterator is invalid.
Definition: SequenceIterator.hpp:92
value_type reference
The reference type is the same as the value type, an Offset.
Definition: SequenceIterator.hpp:59
friend bool operator<=(const SequenceIterator &s1, const SequenceIterator &s2)
Compares two iterators.
Definition: SequenceIterator.hpp:192
SequenceIterator & operator++()
Advances to the next element.
Definition: SequenceIterator.hpp:147
bool advance()
Advances to the next element, reporting any errors by returning false.
Definition: SequenceIterator.hpp:132
value_type operator->() const
Returns the Offset of the current element.
Definition: SequenceIterator.hpp:113
friend bool operator!=(const SequenceIterator &s1, const SequenceIterator &s2)
Compares two iterators.
Definition: SequenceIterator.hpp:222
std::forward_iterator_tag iterator_category
The iterator category.
Definition: SequenceIterator.hpp:49
The RTI namespace.
Definition: AggregationBuilders.hpp:17