/************************************************************************************ * * * Copyright (c) 2014 - 2018 Axel Menzel * * * * This file is part of RTTR (Run Time Type Reflection) * * License: MIT License * * * * Permission is hereby granted, free of charge, to any person obtaining * * a copy of this software and associated documentation files (the "Software"), * * to deal in the Software without restriction, including without limitation * * the rights to use, copy, modify, merge, publish, distribute, sublicense, * * and/or sell copies of the Software, and to permit persons to whom the * * Software is furnished to do so, subject to the following conditions: * * * * The above copyright notice and this permission notice shall be included in * * all copies or substantial portions of the Software. * * * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * * SOFTWARE. * * * *************************************************************************************/ #ifndef RTTR_ARRAY_RANGE_IMPL_H_ #define RTTR_ARRAY_RANGE_IMPL_H_ #include "rttr/detail/base/core_prerequisites.h" #include "rttr/property.h" #include "rttr/type.h" #include namespace rttr { ///////////////////////////////////////////////////////////////////////////////////////// template RTTR_INLINE array_range::array_range(const T* begin, size_type size, const Predicate& pred) : m_begin(begin), m_end(begin + size), m_pred(pred) { } ///////////////////////////////////////////////////////////////////////////////////////// template RTTR_INLINE array_range::array_range() : m_begin(nullptr), m_end(nullptr) { } ///////////////////////////////////////////////////////////////////////////////////////// template RTTR_INLINE typename array_range::const_iterator array_range::begin() { if (empty_()) { return {m_end, this}; } else { const_iterator itr(m_begin, this); if (m_pred(*itr)) return itr; next(itr); return itr; } } ///////////////////////////////////////////////////////////////////////////////////////// template RTTR_INLINE typename array_range::const_iterator array_range::end() { return {m_end, this}; } ///////////////////////////////////////////////////////////////////////////////////////// template RTTR_INLINE typename array_range::const_iterator array_range::begin() const { if (empty_()) { return {m_end, this}; } else { const_iterator itr(m_begin, this); if (m_pred(*itr)) return itr; next(itr); return itr; } } ///////////////////////////////////////////////////////////////////////////////////////// template RTTR_INLINE typename array_range::const_iterator array_range::end() const { return {m_end, this}; } ///////////////////////////////////////////////////////////////////////////////////////// template RTTR_INLINE typename array_range::const_iterator array_range::cbegin() const { if (empty_()) { return {m_end, this}; } else { const_iterator itr(m_begin, this); if (m_pred(*itr)) return itr; next(itr); return itr; } } ///////////////////////////////////////////////////////////////////////////////////////// template RTTR_INLINE typename array_range::const_iterator array_range::cend() const { return {m_end, this}; } ///////////////////////////////////////////////////////////////////////////////////////// template RTTR_INLINE typename array_range::const_reverse_iterator array_range::rbegin() { if (empty_()) { return {m_end, this}; } else { const_reverse_iterator itr(m_end, this); if (m_pred(*itr)) return itr; prev(itr); return itr; } } ///////////////////////////////////////////////////////////////////////////////////////// template RTTR_INLINE typename array_range::const_reverse_iterator array_range::rend() { return const_reverse_iterator{m_begin, this}; } ///////////////////////////////////////////////////////////////////////////////////////// template RTTR_INLINE typename array_range::const_reverse_iterator array_range::rbegin() const { if (empty_()) { return {m_end, this}; } else { const_reverse_iterator itr(m_end, this); if (m_pred(*itr)) return itr; prev(itr); return itr; } } ///////////////////////////////////////////////////////////////////////////////////////// template RTTR_INLINE typename array_range::const_reverse_iterator array_range::rend() const { return const_reverse_iterator{m_begin, this}; } ///////////////////////////////////////////////////////////////////////////////////////// template RTTR_INLINE typename array_range::const_reverse_iterator array_range::crbegin() const { if (empty_()) { return {m_end, this}; } else { const_reverse_iterator itr(m_end, this); if (m_pred(*itr)) return itr; prev(itr); return itr; } } ///////////////////////////////////////////////////////////////////////////////////////// template RTTR_INLINE typename array_range::const_reverse_iterator array_range::crend() const { return const_reverse_iterator{m_begin, this}; } ///////////////////////////////////////////////////////////////////////////////////////// template RTTR_INLINE size_t array_range::size() const { std::size_t result = 0; const_iterator itr{m_begin, this}; while(itr != cend()) { if (m_pred(*itr.m_ptr)) ++result; ++itr.m_ptr; } return result; } ///////////////////////////////////////////////////////////////////////////////////////// template RTTR_INLINE bool array_range::empty() const { if (m_begin == m_end) return true; const_iterator itr{m_begin, this}; if (m_pred(*itr)) return false; ++itr.m_ptr; while(itr.m_ptr != m_end && !m_pred(*itr.m_ptr)) { ++itr.m_ptr; } return (itr == cend()); } ///////////////////////////////////////////////////////////////////////////////////////// template RTTR_INLINE bool array_range::empty_() const { return (m_begin == m_end); } ///////////////////////////////////////////////////////////////////////////////////////// template template RTTR_INLINE void array_range::next(array_iterator& itr) const { ++itr.m_ptr; while(itr.m_ptr != m_end && !m_pred(*itr.m_ptr)) { ++itr.m_ptr; } } ///////////////////////////////////////////////////////////////////////////////////////// template template RTTR_INLINE void array_range::prev(array_reverse_iterator& itr) const { --itr.m_ptr; while(itr.m_ptr != (m_begin - 1) && !m_pred(*itr.m_ptr)) { --itr.m_ptr; } } ///////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////// template template RTTR_INLINE array_range::array_iterator_base::array_iterator_base() : m_ptr(nullptr) { } ///////////////////////////////////////////////////////////////////////////////////////// template template RTTR_INLINE array_range::array_iterator_base::array_iterator_base(typename array_iterator_base::pointer ptr, const array_range* const range) : m_ptr(ptr), m_range(range) { } ///////////////////////////////////////////////////////////////////////////////////////// template template RTTR_INLINE bool array_range::array_iterator_base::operator==(const self_type& rhs) const { return (m_ptr == rhs.m_ptr); } ///////////////////////////////////////////////////////////////////////////////////////// template template RTTR_INLINE bool array_range::array_iterator_base::operator!=(const self_type& rhs) const { return (m_ptr != rhs.m_ptr); } ///////////////////////////////////////////////////////////////////////////////////////// template template RTTR_INLINE typename array_range::template array_iterator_base::self_type& array_range::array_iterator_base::operator=(const self_type& other) { m_ptr = other.m_ptr; return *this; } ///////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////// template template RTTR_INLINE array_range::array_iterator::array_iterator() { } ///////////////////////////////////////////////////////////////////////////////////////// template template RTTR_INLINE array_range::array_iterator::array_iterator(const array_iterator& other) : array_iterator_base(other.m_ptr, other.m_range) { } ///////////////////////////////////////////////////////////////////////////////////////// template template RTTR_INLINE array_range::array_iterator::array_iterator(typename array_iterator_base::pointer ptr, const array_range* const range) : array_iterator_base(ptr, range) { } ///////////////////////////////////////////////////////////////////////////////////////// template template RTTR_INLINE typename array_range::template array_iterator::reference array_range::array_iterator::operator*() const { return *this->m_ptr; } ///////////////////////////////////////////////////////////////////////////////////////// template template RTTR_INLINE typename array_range::template array_iterator::pointer array_range::array_iterator::operator->() { return this->m_ptr; } ///////////////////////////////////////////////////////////////////////////////////////// template template RTTR_INLINE typename array_range::template array_iterator::self_type& array_range::array_iterator::operator++() { this->m_range->next(*this); return *this; } ///////////////////////////////////////////////////////////////////////////////////////// template template RTTR_INLINE typename array_range::template array_iterator::self_type array_range::array_iterator::operator++(int index) { auto old_itr = *this; this->m_range->next(*this); return old_itr; } ///////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////// template template RTTR_INLINE array_range::array_reverse_iterator::array_reverse_iterator() { } ///////////////////////////////////////////////////////////////////////////////////////// template template RTTR_INLINE array_range::array_reverse_iterator::array_reverse_iterator(const array_reverse_iterator& other) : array_iterator_base(other.m_ptr, other.m_range) { } ///////////////////////////////////////////////////////////////////////////////////////// template template RTTR_INLINE array_range::array_reverse_iterator::array_reverse_iterator(typename array_iterator_base::pointer ptr, const array_range* const range) : array_iterator_base(ptr, range) { } ///////////////////////////////////////////////////////////////////////////////////////// template template RTTR_INLINE typename array_range::template array_reverse_iterator::reference array_range::array_reverse_iterator::operator*() const { auto tmp = this->m_ptr; return (*--tmp); } ///////////////////////////////////////////////////////////////////////////////////////// template template RTTR_INLINE typename array_range::template array_reverse_iterator::pointer array_range::array_reverse_iterator::operator->() { auto tmp = this->m_ptr; return --tmp; } //////////////////////////////////////////////////////////////////////////////////////////// template template RTTR_INLINE typename array_range::template array_reverse_iterator::self_type& array_range::array_reverse_iterator::operator++() { this->m_range->prev(*this); return *this; } ///////////////////////////////////////////////////////////////////////////////////////// template template RTTR_INLINE typename array_range::template array_reverse_iterator::self_type array_range::array_reverse_iterator::operator++(int index) { auto old_itr = *this; this->m_range->prev(*this); return old_itr; } ///////////////////////////////////////////////////////////////////////////////////////// namespace detail { template struct default_predicate { RTTR_FORCE_INLINE default_predicate() {} RTTR_FORCE_INLINE default_predicate(std::function func) : m_func(std::move(func)) {} RTTR_FORCE_INLINE bool operator()(const T& obj) const { return (m_func ? m_func(obj) : true); } std::function m_func; }; ///////////////////////////////////////////////////////////////////////////////////////// } // end namespace detail } // end namespace rttr #endif // RTTR_ITEM_RANGE_IMPL_H_