//============================================================================ // Copyright (c) Kitware, Inc. // All rights reserved. // See LICENSE.txt for details. // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notice for more information. // // Copyright 2014 Sandia Corporation. // Copyright 2014 UT-Battelle, LLC. // Copyright 2014 Los Alamos National Security. // // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, // the U.S. Government retains certain rights in this software. // // Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National // Laboratory (LANL), the U.S. Government retains certain rights in // this software. //============================================================================ #ifndef vtk_m_cont_internal_IteratorFromArrayPortal_h #define vtk_m_cont_internal_IteratorFromArrayPortal_h #include #include #include namespace vtkm { namespace cont { namespace internal { namespace detail { template struct IteratorFromArrayPortalValue { typedef typename ArrayPortalType::ValueType ValueType; VTKM_CONT_EXPORT IteratorFromArrayPortalValue(const ArrayPortalType &portal, vtkm::Id index) : Portal(portal), Index(index) { } VTKM_CONT_EXPORT void Swap( IteratorFromArrayPortalValue &rhs ) throw() { //we need use the explicit type not a proxy temp object //A proxy temp object would point to the same underlying data structure //and would not hold the old value of *this once *this was set to rhs. const ValueType aValue = *this; *this = rhs; rhs = aValue; } VTKM_CONT_EXPORT IteratorFromArrayPortalValue &operator=( const IteratorFromArrayPortalValue &rhs) { this->Portal.Set(this->Index, rhs.Portal.Get(rhs.Index)); return *this; } VTKM_CONT_EXPORT ValueType operator=(const ValueType& value) { this->Portal.Set(this->Index, value); return value; } VTKM_CONT_EXPORT bool operator<(const ValueType& value) const { return this->Portal.Get(this->Index) < value; } VTKM_CONT_EXPORT operator ValueType(void) const { return this->Portal.Get(this->Index); } const ArrayPortalType& Portal; vtkm::Id Index; }; } // namespace detail template class IteratorFromArrayPortal : public boost::iterator_facade< IteratorFromArrayPortal, typename ArrayPortalType::ValueType, boost::random_access_traversal_tag, detail::IteratorFromArrayPortalValue, vtkm::Id> { public: VTKM_CONT_EXPORT IteratorFromArrayPortal() : Portal(), Index(0) { } VTKM_CONT_EXPORT explicit IteratorFromArrayPortal(const ArrayPortalType &portal, vtkm::Id index = 0) : Portal(portal), Index(index) { } VTKM_CONT_EXPORT detail::IteratorFromArrayPortalValue operator[](std::size_t idx) const { return detail::IteratorFromArrayPortalValue(this->Portal, this->Index + static_cast(idx) ); } private: ArrayPortalType Portal; vtkm::Id Index; // Implementation for boost iterator_facade friend class boost::iterator_core_access; VTKM_CONT_EXPORT detail::IteratorFromArrayPortalValue dereference() const { return detail::IteratorFromArrayPortalValue(this->Portal, this->Index); } VTKM_CONT_EXPORT bool equal(const IteratorFromArrayPortal &other) const { // Technically, we should probably check that the portals are the same, // but the portal interface does not specify an equal operator. It is // by its nature undefined what happens when comparing iterators from // different portals anyway. return (this->Index == other.Index); } VTKM_CONT_EXPORT void increment() { this->Index++; VTKM_ASSERT_CONT(this->Index >= 0); VTKM_ASSERT_CONT(this->Index <= this->Portal.GetNumberOfValues()); } VTKM_CONT_EXPORT void decrement() { this->Index--; VTKM_ASSERT_CONT(this->Index >= 0); VTKM_ASSERT_CONT(this->Index <= this->Portal.GetNumberOfValues()); } VTKM_CONT_EXPORT void advance(vtkm::Id delta) { this->Index += delta; VTKM_ASSERT_CONT(this->Index >= 0); VTKM_ASSERT_CONT(this->Index <= this->Portal.GetNumberOfValues()); } VTKM_CONT_EXPORT vtkm::Id distance_to(const IteratorFromArrayPortal &other) const { // Technically, we should probably check that the portals are the same, // but the portal interface does not specify an equal operator. It is // by its nature undefined what happens when comparing iterators from // different portals anyway. return other.Index - this->Index; } }; template IteratorFromArrayPortal make_IteratorBegin( const ArrayPortalType &portal) { return IteratorFromArrayPortal(portal, 0); } template IteratorFromArrayPortal make_IteratorEnd( const ArrayPortalType &portal) { return IteratorFromArrayPortal(portal, portal.GetNumberOfValues()); } //implementat a custom swap function, since the std::swap won't work //since we return RValues instead of Lvalues template void swap( vtkm::cont::internal::detail::IteratorFromArrayPortalValue a, vtkm::cont::internal::detail::IteratorFromArrayPortalValue b) { a.Swap(b); } } } } // namespace vtkm::cont::internal #endif //vtk_m_cont_internal_IteratorFromArrayPortal_h