//============================================================================ // 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_ArrayPortalFromIterators_h #define vtk_m_cont_internal_ArrayPortalFromIterators_h #include #include #include #include #include #include #include #include namespace vtkm { namespace cont { namespace internal { template class ArrayPortalFromIterators; /// This templated implementation of an ArrayPortal allows you to adapt a pair /// of begin/end iterators to an ArrayPortal interface. /// template class ArrayPortalFromIterators::type > >::type> { public: typedef typename std::iterator_traits::value_type ValueType; typedef IteratorT IteratorType; VTKM_SUPPRESS_EXEC_WARNINGS VTKM_CONT_EXPORT ArrayPortalFromIterators() { } VTKM_SUPPRESS_EXEC_WARNINGS VTKM_CONT_EXPORT ArrayPortalFromIterators(IteratorT begin, IteratorT end) : BeginIterator(begin) { typename std::iterator_traits::difference_type numberOfValues = std::distance(begin, end); VTKM_ASSERT(numberOfValues >= 0); #ifndef VTKM_USE_64BIT_IDS if (numberOfValues > (std::numeric_limits::max)()) { throw vtkm::cont::ErrorControlBadAllocation( "Distance of iterators larger than maximum array size. " "To support larger arrays, try turning on VTKM_USE_64BIT_IDS."); } #endif // !VTKM_USE_64BIT_IDS this->NumberOfValues = static_cast(numberOfValues); } /// Copy constructor for any other ArrayPortalFromIterators with an iterator /// type that can be copied to this iterator type. This allows us to do any /// type casting that the iterators do (like the non-const to const cast). /// template VTKM_CONT_EXPORT ArrayPortalFromIterators(const ArrayPortalFromIterators &src) : BeginIterator(src.GetIteratorBegin()), NumberOfValues(src.GetNumberOfValues()) { } VTKM_SUPPRESS_EXEC_WARNINGS VTKM_EXEC_CONT_EXPORT vtkm::Id GetNumberOfValues() const { return this->NumberOfValues; } VTKM_SUPPRESS_EXEC_WARNINGS VTKM_EXEC_CONT_EXPORT ValueType Get(vtkm::Id index) const { return *this->IteratorAt(index); } VTKM_SUPPRESS_EXEC_WARNINGS VTKM_EXEC_CONT_EXPORT void Set(vtkm::Id index, const ValueType& value) const { *(this->BeginIterator + index) = value; } VTKM_SUPPRESS_EXEC_WARNINGS VTKM_EXEC_CONT_EXPORT IteratorT GetIteratorBegin() const { return this->BeginIterator; } private: IteratorT BeginIterator; vtkm::Id NumberOfValues; VTKM_SUPPRESS_EXEC_WARNINGS VTKM_EXEC_CONT_EXPORT IteratorT IteratorAt(vtkm::Id index) const { VTKM_ASSERT(index >= 0); VTKM_ASSERT(index < this->GetNumberOfValues()); return this->BeginIterator + index; } }; template class ArrayPortalFromIterators::type > >::type> { public: typedef typename std::iterator_traits::value_type ValueType; typedef IteratorT IteratorType; VTKM_SUPPRESS_EXEC_WARNINGS VTKM_CONT_EXPORT ArrayPortalFromIterators() { } VTKM_SUPPRESS_EXEC_WARNINGS VTKM_CONT_EXPORT ArrayPortalFromIterators(IteratorT begin, IteratorT end) : BeginIterator(begin) { typename std::iterator_traits::difference_type numberOfValues = std::distance(begin, end); VTKM_ASSERT(numberOfValues >= 0); #ifndef VTKM_USE_64BIT_IDS if (numberOfValues > (std::numeric_limits::max)()) { throw vtkm::cont::ErrorControlBadAllocation( "Distance of iterators larger than maximum array size. " "To support larger arrays, try turning on VTKM_USE_64BIT_IDS."); } #endif // !VTKM_USE_64BIT_IDS this->NumberOfValues = static_cast(numberOfValues); } /// Copy constructor for any other ArrayPortalFromIterators with an iterator /// type that can be copied to this iterator type. This allows us to do any /// type casting that the iterators do (like the non-const to const cast). /// template VTKM_CONT_EXPORT ArrayPortalFromIterators(const ArrayPortalFromIterators &src) : BeginIterator(src.GetIteratorBegin()), NumberOfValues(src.GetNumberOfValues()) { } VTKM_SUPPRESS_EXEC_WARNINGS VTKM_EXEC_CONT_EXPORT vtkm::Id GetNumberOfValues() const { return this->NumberOfValues; } VTKM_SUPPRESS_EXEC_WARNINGS VTKM_EXEC_CONT_EXPORT ValueType Get(vtkm::Id index) const { return *this->IteratorAt(index); } VTKM_SUPPRESS_EXEC_WARNINGS VTKM_EXEC_CONT_EXPORT IteratorT GetIteratorBegin() const { return this->BeginIterator; } private: IteratorT BeginIterator; vtkm::Id NumberOfValues; VTKM_SUPPRESS_EXEC_WARNINGS VTKM_EXEC_CONT_EXPORT IteratorT IteratorAt(vtkm::Id index) const { VTKM_ASSERT(index >= 0); VTKM_ASSERT(index < this->GetNumberOfValues()); return this->BeginIterator + index; } }; } } } // namespace vtkm::cont::internal namespace vtkm { namespace cont { /// Partial specialization of \c ArrayPortalToIterators for \c /// ArrayPortalFromIterators. Returns the original array rather than /// the portal wrapped in an \c IteratorFromArrayPortal. /// template class ArrayPortalToIterators< vtkm::cont::internal::ArrayPortalFromIterators<_IteratorType> > { typedef vtkm::cont::internal::ArrayPortalFromIterators<_IteratorType> PortalType; public: #if !defined(VTKM_MSVC) || (defined(_ITERATOR_DEBUG_LEVEL) && _ITERATOR_DEBUG_LEVEL == 0) typedef _IteratorType IteratorType; VTKM_SUPPRESS_EXEC_WARNINGS VTKM_EXEC_CONT_EXPORT ArrayPortalToIterators(const PortalType &portal) : Iterator(portal.GetIteratorBegin()), NumberOfValues(portal.GetNumberOfValues()) { } #else // VTKM_MSVC // The MSVC compiler issues warnings when using raw pointer math when in // debug mode. To keep the compiler happy (and add some safety checks), // wrap the iterator in checked_array_iterator. typedef stdext::checked_array_iterator<_IteratorType> IteratorType; VTKM_SUPPRESS_EXEC_WARNINGS VTKM_EXEC_CONT_EXPORT ArrayPortalToIterators(const PortalType &portal) : Iterator(portal.GetIteratorBegin(), static_cast(portal.GetNumberOfValues())), NumberOfValues(portal.GetNumberOfValues()) { } #endif // VTKM_MSVC VTKM_SUPPRESS_EXEC_WARNINGS VTKM_EXEC_CONT_EXPORT IteratorType GetBegin() const { return this->Iterator; } VTKM_SUPPRESS_EXEC_WARNINGS VTKM_EXEC_CONT_EXPORT IteratorType GetEnd() const { IteratorType iterator = this->Iterator; typedef typename std::iterator_traits::difference_type difference_type; #if !defined(VTKM_MSVC) || (defined(_ITERATOR_DEBUG_LEVEL) && _ITERATOR_DEBUG_LEVEL == 0) std::advance(iterator, static_cast(this->NumberOfValues)); #else //Visual Studio checked iterators throw exceptions when you try to advance //NULL iterators even if the advancement length is zero. So instead //don't do the advancement at all if(this->NumberOfValues > 0) { std::advance(iterator, static_cast(this->NumberOfValues)); } #endif return iterator; } private: IteratorType Iterator; vtkm::Id NumberOfValues; }; } } // namespace vtkm::cont #endif //vtk_m_cont_internal_ArrayPortalFromIterators_h