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