/*========================================================================= * * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ #ifndef itkArray_h #define itkArray_h #include "itkMacro.h" #include "vxl_version.h" #include "vnl/vnl_vector.h" namespace itk { /** * \class Array * \brief Array class with size defined at construction time. * * This class derives from the vnl_vector<> class. * Its size is assigned at construction time (run time) and can * not be changed afterwards except by using assignment to another * Array. * * The class is templated over the type of the elements. * * Template parameters for class Array: * * - TValue = Element type stored at each location in the array. * * \ingroup DataRepresentation * \ingroup ITKCommon */ template class ITK_TEMPLATE_EXPORT Array : public vnl_vector { public: /** The element type stored at each location in the Array. */ using ValueType = TValue; using Self = Array; using VnlVectorType = vnl_vector; using SizeValueType = typename vnl_vector::size_type; public: /** Default constructor. It is created with an empty array * it has to be allocated later by assignment */ Array() = default; /** Copy constructor. Uses VNL copy constructor with correct * setting for memory management. */ Array(const Array &); /** Construct from a VnlVectorType */ explicit Array(const VnlVectorType &); /** Constructor with size. Size can only be changed by assignment. * \note This constructor may not initialize its elements. */ explicit Array(SizeValueType dimension); /** Constructor with size and initial value for each element. */ explicit Array(SizeValueType dimension, const ValueType & value); /** Constructor that initializes array with contents from a user supplied * buffer. The pointer to the buffer and the length is specified. By default, * the array does not manage the memory of the buffer. It merely points to * that location and it is the user's responsibility to delete it. * If "LetArrayManageMemory" is true, then this class will free the * memory when this object is destroyed. */ Array(ValueType * datain, SizeValueType sz, bool LetArrayManageMemory = false); #if defined(ITK_LEGACY_REMOVE) /** Constructor that initializes array with contents from a user supplied * const buffer. The pointer to the buffer and the length is specified. By default, * the array does a deep copy of the const pointer data, so the array class also * manages memory. */ Array(const ValueType * datain, SizeValueType sz); #else // defined ( ITK_LEGACY_REMOVE ) /** Constructor that initializes array with contents from a user supplied * buffer. The pointer to the buffer and the length is specified. The array * does a deep copy of the const pointer data, so the array class also * manages memory. The 3rd argument is only for backward compatibility. */ Array(const ValueType * datain, SizeValueType sz, bool LetArrayManageMemory = false); #endif /** Constructor to initialize an array from another of any data type */ template Array(const Array & r) { this->SetSize(r.GetSize()); for (SizeValueType i = 0; i < r.GetSize(); ++i) { this->operator[](i) = static_cast(r[i]); } } /** Set all the elements of the array to the specified value */ void Fill(TValue const & v) { this->fill(v); } /** Copy operator */ Self & operator=(const Self & rhs); Self & operator=(const VnlVectorType & rhs); /** Return the number of elements in the Array */ SizeValueType Size() const { return static_cast(this->size()); } unsigned int GetNumberOfElements() const { return static_cast(this->size()); } /** Get one element */ const TValue & GetElement(SizeValueType i) const { return this->operator[](i); } /** Set one element */ void SetElement(SizeValueType i, const TValue & value) { this->operator[](i) = value; } /** Destructively set the size to that given. Will lose data. */ void SetSize(SizeValueType sz); SizeValueType GetSize() const { return static_cast(this->size()); } /** Set the pointer from which the data is imported. * If "LetArrayManageMemory" is false, then the application retains * the responsibility of freeing the memory for this data. If * "LetArrayManageMemory" is true, then this class will free the * memory when this object is destroyed. * NOTE: This signature requires that internal array is being * replaced by data array of exactly the same size */ void SetDataSameSize(TValue * datain, bool LetArrayManageMemory = false); /** Similar to the previous method. In the above method, the size must be * separately set prior to using user-supplied data. This introduces an * unnecessary allocation step to be performed. This method avoids it * and should be used to import data wherever possible to avoid this. * Set the pointer from which the data is imported. * If "LetArrayManageMemory" is false, then the application retains * the responsibility of freeing the memory for this data. If * "LetArrayManageMemory" is true, then this class will free the * memory when this object is destroyed. */ void SetData(TValue * datain, SizeValueType sz, bool LetArrayManageMemory = false); #ifdef __INTEL_COMPILER # pragma warning disable 444 // destructor for base class "itk::Array<>" is not virtual #endif /** This destructor is not virtual for performance reasons. However, this * means that subclasses cannot allocate memory. */ ~Array() override; #if !defined(ITK_LEGACY_REMOVE) void swap(Array & other) { this->Swap(other); } #endif void Swap(Array & other) { using std::swap; this->VnlVectorType::swap(other); swap(this->m_LetArrayManageMemory, other.m_LetArrayManageMemory); } private: /** Indicates whether this array manages the memory of its data. */ bool m_LetArrayManageMemory{ true }; }; template std::ostream & operator<<(std::ostream & os, const Array & arr) { os << '['; const unsigned int length = arr.size(); if (length >= 1) { const unsigned int last = length - 1; for (unsigned int i = 0; i < last; ++i) { os << arr[i] << ", "; } os << arr[last]; } os << ']'; return os; } // declaration of specialization template <> ITKCommon_EXPORT std::ostream & operator<<(std::ostream & os, const Array & arr); template <> ITKCommon_EXPORT std::ostream & operator<<(std::ostream & os, const Array & arr); template inline void swap(Array & a, Array & b) { a.Swap(b); } } // namespace itk #ifndef ITK_MANUAL_INSTANTIATION # include "itkArray.hxx" #endif #endif