1 /*========================================================================= 2 * 3 * Copyright Insight Software Consortium 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0.txt 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 *=========================================================================*/ 18 #ifndef itkNeighborhoodAllocator_h 19 #define itkNeighborhoodAllocator_h 20 #include <algorithm> 21 #include <iostream> 22 #include "itkMacro.h" 23 24 namespace itk 25 { 26 /** \class NeighborhoodAllocator 27 * \brief A memory allocator for use as the default allocator type in 28 * Neighborhood. 29 * 30 * This is a memory allocator for use as the default allocator type in 31 * Neighborhood. The API is designed to mimic that of vnl_vector so that 32 * vnl_vector can also be used as an allocator for Neighborhood. 33 * 34 * The decision to create this allocator with the vnl_vector api (versus 35 * using an STL allocator and wrapping the vnl_vector API) was made because 36 * the STL allocator API is not guaranteed stable at this time. 37 * 38 * \ingroup Operators 39 * \ingroup ITKCommon 40 */ 41 template< typename TPixel > 42 class NeighborhoodAllocator 43 { 44 public: 45 /** Standard class type aliases. */ 46 using Self = NeighborhoodAllocator; 47 48 /** Iterator support. Note that the naming of the type alias is on purpose. 49 * itk::Neighborhood makes reference to the allocator, which because it may 50 * be vnl or other type, uses the lower case/underscore forms iterator and 51 * const_iterator. */ 52 using iterator = TPixel *; 53 using const_iterator = const TPixel *; 54 55 /** Default constructor */ NeighborhoodAllocator()56 NeighborhoodAllocator(): m_Data(nullptr) {} 57 58 /** Default destructor */ ~NeighborhoodAllocator()59 ~NeighborhoodAllocator() 60 { this->Deallocate(); } 61 62 /** Allocates memory using new() */ Allocate(unsigned int n)63 void Allocate(unsigned int n) 64 { 65 m_Data = new TPixel[n]; 66 m_ElementCount = n; 67 } 68 69 /** Deallocates memory using delete[](). */ Deallocate()70 void Deallocate() 71 { 72 delete[] m_Data; 73 m_ElementCount = 0; 74 } 75 76 /** Copy constructor. */ NeighborhoodAllocator(const Self & other)77 NeighborhoodAllocator(const Self & other): 78 m_ElementCount(other.m_ElementCount), 79 m_Data(new TPixel[other.m_ElementCount]) 80 { 81 std::copy(other.m_Data, other.m_Data + m_ElementCount, m_Data); 82 } 83 84 85 /** Move-constructor. */ NeighborhoodAllocator(Self && other)86 NeighborhoodAllocator(Self&& other) ITK_NOEXCEPT 87 : 88 m_ElementCount{ other.m_ElementCount }, 89 m_Data{ other.m_Data } 90 { 91 other.m_ElementCount = 0; 92 other.m_Data = nullptr; 93 } 94 95 96 /** Assignment operator. */ 97 Self & operator=(const Self & other) 98 { 99 if(this != &other) 100 { 101 this->set_size(other.m_ElementCount); 102 std::copy(other.m_Data, other.m_Data + m_ElementCount, m_Data); 103 } 104 return *this; 105 } 106 107 108 /** Move-assignment. */ 109 Self& operator=(Self&& other) ITK_NOEXCEPT 110 { 111 if (this != &other) 112 { 113 this->Deallocate(); 114 m_ElementCount = other.m_ElementCount; 115 m_Data = other.m_Data; 116 other.m_ElementCount = 0; 117 other.m_Data = nullptr; 118 } 119 return *this; 120 } 121 122 123 /** STL-style iterator support for the memory buffer. */ begin()124 iterator begin() 125 { return m_Data; } begin()126 const_iterator begin() const 127 { return m_Data; } end()128 iterator end() 129 { return ( m_Data + m_ElementCount ); } end()130 const_iterator end() const 131 { return ( m_Data + m_ElementCount ); } size()132 unsigned int size() const 133 { return m_ElementCount; } 134 135 /** Data access methods */ 136 const TPixel & operator[](unsigned int i) const 137 { return m_Data[i]; } 138 TPixel & operator[](unsigned int i) 139 { return m_Data[i]; } 140 141 /** Allocates or Reallocates a buffer of size n */ set_size(unsigned int n)142 void set_size(unsigned int n) 143 { 144 if (n != m_ElementCount) 145 { 146 if ( m_Data ) 147 { 148 this->Deallocate(); 149 } 150 this->Allocate(n); 151 } 152 } 153 154 protected: 155 unsigned int m_ElementCount{0}; 156 TPixel * m_Data; 157 }; 158 159 template< typename TPixel > 160 inline std::ostream & operator<<( 161 std::ostream & o, const NeighborhoodAllocator< TPixel > 162 & a) 163 { 164 o << "NeighborhoodAllocator { this = " << &a << ", begin = " 165 << static_cast< const void * >( a.begin() ) 166 << ", size=" << a.size() 167 << " }"; 168 return o; 169 } 170 171 172 // Equality operator. 173 template< typename TPixel > 174 inline bool operator==( 175 const NeighborhoodAllocator< TPixel >& lhs, 176 const NeighborhoodAllocator< TPixel >& rhs) 177 { 178 const unsigned int size = lhs.size(); 179 return (size == rhs.size()) && 180 ((size == 0) || std::equal(lhs.begin(), lhs.end(), rhs.begin())); 181 } 182 183 // Inequality operator. 184 template< typename TPixel > 185 inline bool operator!=( 186 const NeighborhoodAllocator< TPixel >& lhs, 187 const NeighborhoodAllocator< TPixel >& rhs) 188 { 189 return ! (lhs == rhs); 190 } 191 } // end namespace itk 192 #endif 193