/* $Id$ (c) Copyright, Real-Time Innovations, 2014-2016. All rights reserved. No duplications, whole or partial, manual or electronic, may be made without express written permission. Any such copies, or revisions thereof, must display this notice unaltered. This code contains trade secrets of Real-Time Innovations, Inc. modification history -------------------- 1.0a,05may14,acr Added ValidSampleIterator and valid_samples helper 1.0a,20mar13,acr Created ============================================================================= */ #ifndef RTI_ROUTING_PROCESSOR_SAMPLE_ITERATOR_HPP_ #define RTI_ROUTING_PROCESSOR_SAMPLE_ITERATOR_HPP_ #include #include namespace rti { namespace routing { namespace processor { /*i * @brief Tag type to emulate/indicate that sample infos are not available */ struct no_sample_info_t { }; /** * @ingroup RTI_RoutingServiceProcessorModule * * @class rti::routing::processor::SampleIterator * @brief A random-access iterator of LoanedSample * * @see rti::routing::processor::LoanedSamples */ template class SampleIterator { public: // iterator traits using iterator_category = std::random_access_iterator_tag; using value_type = const LoanedSample; using reference = value_type; using pointer = value_type; using difference_type = std::size_t; using SampleSeqType = RTI_RoutingServiceSample*; using InfoSeqType = RTI_RoutingServiceSampleInfo*; private: static no_sample_info_t *_null_info_scrachtpad[1]; static InfoSeqType _null_info_seq; static difference_type _null_info_pos; public: SampleIterator() : _sample_seq(0), _info_seq(0), _length(0), _pos(0), _info_pos(_pos) { } SampleIterator( const SampleSeqType sample_seq, const InfoSeqType info_seq, int length, int position = 0) : _sample_seq(sample_seq), _info_seq(info_seq == NULL ? _null_info_seq : info_seq), _length(length), _info_pos(info_seq == NULL ? _null_info_pos : _pos) { if (position < 0) { throw dds::core::IllegalOperationError("SampleIterator out of range"); } _pos = static_cast(position); } SampleIterator(const SampleIterator & other) : _sample_seq(other._sample_seq), _info_seq(other._info_seq), _length(other._length), _pos(other._pos), _info_pos(other._info_pos) { } SampleIterator & operator=(const SampleIterator & other) { _sample_seq = other._sample_seq; _info_seq = other._info_seq; _length = other._length; _pos = other._pos; _info_pos = other._info_pos; return *this; } value_type operator*() const { return value_type(_sample_seq[_pos], _info_seq[_info_pos]); } value_type operator->() const { return value_type(_sample_seq[_pos], _info_seq[_info_pos]); } value_type operator[](difference_type offset) const { return (_info_seq == _null_info_seq) ? value_type(_sample_seq[_pos], NULL) : value_type(_sample_seq[_pos + offset], _info_seq[_info_pos + offset]); } /* * Windows defines min and max in one of the Windows headers, and they * collide with the max() definition we use below */ #ifdef RTI_WIN32 #undef max #undef min #endif SampleIterator & operator++() { if (_pos == std::numeric_limits::max()) { throw dds::core::IllegalOperationError("SampleIterator out of range"); } ++_pos; return *this; } SampleIterator operator++(int) { SampleIterator temp(*this); ++(*this); return temp; } SampleIterator & operator--() { if (_pos == std::numeric_limits::min()) { throw dds::core::IllegalOperationError("SampleIterator out of range"); } --_pos; return *this; } SampleIterator operator--(int) { SampleIterator temp(*this); --(*this); return temp; } SampleIterator & operator-=(difference_type i) { if (i > _pos) { throw dds::core::IllegalOperationError("SampleIterator out of range"); } _pos -= i; return *this; } SampleIterator & operator+=(difference_type i) { if ((std::numeric_limits::max() - _pos) < i) { throw dds::core::IllegalOperationError("SampleIterator out of range"); } _pos += i; return *this; } friend SampleIterator operator-( const SampleIterator& si, difference_type i) { SampleIterator temp(si); temp -= i; return temp; } friend SampleIterator operator+( const SampleIterator& si, difference_type i) { SampleIterator temp(si); temp += i; return temp; } friend difference_type operator-( const SampleIterator& s1, const SampleIterator& s2) { return s1._pos - s2._pos; } friend bool operator<(const SampleIterator & s1, const SampleIterator & s2) { return s1._pos < s2._pos; } friend bool operator>(const SampleIterator & s1, const SampleIterator & s2) { return s1._pos > s2._pos; } friend bool operator<=(const SampleIterator & s1, const SampleIterator & s2) { return s1._pos <= s2._pos; } friend bool operator>=(const SampleIterator & s1, const SampleIterator & s2) { return s1._pos >= s2._pos; } friend bool operator==(const SampleIterator & s1, const SampleIterator & s2) { return (s1._sample_seq == s2._sample_seq) && (s1._pos == s2._pos); } friend bool operator!=(const SampleIterator & s1, const SampleIterator & s2) { return !(s1 == s2); } bool is_end() const { return (_length == _pos); } // Keep these members public otherwise some of the // converting constructors will not compile. public: SampleSeqType _sample_seq; InfoSeqType _info_seq; int _length; difference_type _pos; difference_type& _info_pos; }; template std::size_t SampleIterator::_null_info_pos = 0; template no_sample_info_t * SampleIterator::_null_info_scrachtpad[1] = {NULL}; template typename SampleIterator::InfoSeqType SampleIterator::_null_info_seq = reinterpret_cast (SampleIterator::_null_info_scrachtpad); } } } #endif // RTI_ROUTING_PROCESSOR_SAMPLE_ITERATOR_HPP_