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 itkVectorContainer_hxx
19 #define itkVectorContainer_hxx
20 #include "itkVectorContainer.h"
21 
22 #include "itkNumericTraits.h"
23 
24 namespace itk
25 {
26 /**
27  * Get a reference to the element at the given index.
28  * It is assumed that the index exists, and it will not automatically
29  * be created.
30  *
31  * It is assumed that the value of the element is modified through the
32  * reference.
33  */
34 template< typename TElementIdentifier, typename TElement >
35 auto
36 VectorContainer< TElementIdentifier, TElement >
ElementAt(ElementIdentifier id)37 ::ElementAt(ElementIdentifier id) -> reference
38 {
39   this->Modified();
40   return this->VectorType::operator[](id);
41 }
42 
43 /**
44  * Get a reference to the element at the given index.
45  * It is assumed that the index exists, and it will not automatically
46  * be created.
47  *
48  */
49 template< typename TElementIdentifier, typename TElement >
50 auto
51 VectorContainer< TElementIdentifier, TElement >
ElementAt(ElementIdentifier id) const52 ::ElementAt(ElementIdentifier id) const -> const_reference
53 {
54   return this->VectorType::operator[](id);
55 }
56 
57 /**
58  * Get a reference to the element at the given index.
59  * If the element location does not exist, it will be created with a
60  * default element value.
61  *
62  * It is assumed that the value of the element is modified through the
63  * reference.
64  */
65 template< typename TElementIdentifier, typename TElement >
66 auto
67 VectorContainer< TElementIdentifier, TElement >
CreateElementAt(ElementIdentifier id)68 ::CreateElementAt(ElementIdentifier id) -> reference
69 {
70   if ( id >= static_cast<ElementIdentifier>(this->VectorType::size()) )
71     {
72     this->CreateIndex(id);
73     }
74   this->Modified();
75   return this->VectorType::operator[](id);
76 }
77 
78 /**
79  * Read the element from the given index.
80  * It is assumed that the index exists.
81  */
82 template< typename TElementIdentifier, typename TElement >
83 typename VectorContainer< TElementIdentifier, TElement >::Element
84 VectorContainer< TElementIdentifier, TElement >
GetElement(ElementIdentifier id) const85 ::GetElement(ElementIdentifier id) const
86 {
87   return this->VectorType::operator[](id);
88 }
89 
90 /**
91  * Set the element value at the given index.
92  * It is assumed that the index exists.
93  */
94 template< typename TElementIdentifier, typename TElement >
95 void
96 VectorContainer< TElementIdentifier, TElement >
SetElement(ElementIdentifier id,Element element)97 ::SetElement(ElementIdentifier id, Element element)
98 {
99   this->VectorType::operator[](id) = element;
100   this->Modified();
101 }
102 
103 /**
104  * Set the element value at the given index.
105  * If the element location does not exist, it will be created with a
106  * default element value.
107  */
108 template< typename TElementIdentifier, typename TElement >
109 void
110 VectorContainer< TElementIdentifier, TElement >
InsertElement(ElementIdentifier id,Element element)111 ::InsertElement(ElementIdentifier id, Element element)
112 {
113   if ( id >= static_cast< ElementIdentifier >( this->VectorType::size() ) )
114     {
115     this->CreateIndex(id);
116     }
117   this->VectorType::operator[](id) = element;
118 
119   this->Modified();
120 }
121 
122 /**
123  * Check if the index range of the STL vector is large enough to allow the
124  * given index without expansion.
125  */
126 template< typename TElementIdentifier, typename TElement >
127 bool
128 VectorContainer< TElementIdentifier, TElement >
IndexExists(ElementIdentifier identifier) const129 ::IndexExists(ElementIdentifier identifier) const
130 {
131   return ( NumericTraits< ElementIdentifier >::IsNonnegative(identifier)
132            && ( identifier < static_cast<ElementIdentifier>(this->VectorType::size()) ) );
133 }
134 
135 /**
136  * Check if the given index is in range of the STL vector.  If it is not,
137  * return false.  Otherwise, set the element through the pointer (if it isn't
138  * nullptr), and return true.
139  */
140 template< typename TElementIdentifier, typename TElement >
141 bool
142 VectorContainer< TElementIdentifier, TElement >
GetElementIfIndexExists(ElementIdentifier identifier,Element * element) const143 ::GetElementIfIndexExists(ElementIdentifier identifier, Element *element) const
144 {
145   if ( NumericTraits< ElementIdentifier >::IsNonnegative(identifier)
146        && ( identifier < static_cast<ElementIdentifier>(this->VectorType::size()) ) )
147     {
148     if ( element )
149       {
150       *element = this->VectorType::operator[](identifier);
151       }
152     return true;
153     }
154   return false;
155 }
156 
157 /**
158  * Make sure that the index range of the STL vector is large enough to allow
159  * the given index, expanding it if necessary.  The index will contain
160  * the default element regardless of whether expansion occurred.
161  */
162 template< typename TElementIdentifier, typename TElement >
163 void
164 VectorContainer< TElementIdentifier, TElement >
CreateIndex(ElementIdentifier id)165 ::CreateIndex(ElementIdentifier id)
166 {
167   if ( id >= static_cast< ElementIdentifier >( this->VectorType::size() ) )
168     {
169     /**
170      * The vector must be expanded to fit the
171      * new id.
172      */
173     this->VectorType::resize(id + 1);
174     this->Modified();
175     }
176   else if ( id > 0 )
177     {
178     /**
179      * No expansion was necessary.  Just overwrite the index's entry with
180      * the default element.
181      */
182     this->VectorType::operator[](id) = Element();
183 
184     this->Modified();
185     }
186 }
187 
188 /**
189  * It doesn't make sense to delete a vector index.
190  * Instead, just overwrite the index with the default element.
191  */
192 template< typename TElementIdentifier, typename TElement >
193 void
194 VectorContainer< TElementIdentifier, TElement >
DeleteIndex(ElementIdentifier id)195 ::DeleteIndex(ElementIdentifier id)
196 {
197   this->VectorType::operator[](id) = Element();
198   this->Modified();
199 }
200 
201 /**
202  * Get a begin const iterator for the vector.
203  */
204 template< typename TElementIdentifier, typename TElement >
205 typename VectorContainer< TElementIdentifier, TElement >::ConstIterator
206 VectorContainer< TElementIdentifier, TElement >
Begin() const207 ::Begin() const
208 {
209   return ConstIterator( 0, this->VectorType::begin() );
210 }
211 
212 /**
213  * Get an end const iterator for the vector.
214  */
215 template< typename TElementIdentifier, typename TElement >
216 typename VectorContainer< TElementIdentifier, TElement >::ConstIterator
217 VectorContainer< TElementIdentifier, TElement >
End() const218 ::End() const
219 {
220   return ConstIterator( this->VectorType::size() - 1, this->VectorType::end() );
221 }
222 
223 /**
224  * Get a begin iterator for the vector.
225  */
226 template< typename TElementIdentifier, typename TElement >
227 typename VectorContainer< TElementIdentifier, TElement >::Iterator
228 VectorContainer< TElementIdentifier, TElement >
Begin()229 ::Begin()
230 {
231   return Iterator( 0, this->VectorType::begin() );
232 }
233 
234 /**
235  * Get an end iterator for the vector.
236  */
237 template< typename TElementIdentifier, typename TElement >
238 typename VectorContainer< TElementIdentifier, TElement >::Iterator
239 VectorContainer< TElementIdentifier, TElement >
End()240 ::End()
241 {
242   return Iterator( this->VectorType::size() - 1, this->VectorType::end() );
243 }
244 
245 /**
246  * Get the number of elements currently stored in the vector.
247  */
248 template< typename TElementIdentifier, typename TElement >
249 typename VectorContainer< TElementIdentifier, TElement >::ElementIdentifier
250 VectorContainer< TElementIdentifier, TElement >
Size() const251 ::Size() const
252 {
253   return static_cast<ElementIdentifier>( this->VectorType::size() );
254 }
255 
256 /**
257  * Clear the elements. The final size will be zero.
258  */
259 template< typename TElementIdentifier, typename TElement >
260 void
261 VectorContainer< TElementIdentifier, TElement >
Initialize()262 ::Initialize()
263 {
264   this->VectorType::clear();
265 }
266 
267 /**
268  *    Allocate memory for at the requested number of elements.
269  */
270 template< typename TElementIdentifier, typename TElement >
271 void
272 VectorContainer< TElementIdentifier, TElement >
Reserve(ElementIdentifier sz)273 ::Reserve(ElementIdentifier sz)
274 {
275   this->CreateIndex(sz - 1);
276 }
277 
278 /**
279  *   Try to compact the internal representation of the memory.
280  */
281 template< typename TElementIdentifier, typename TElement >
282 void
283 VectorContainer< TElementIdentifier, TElement >
Squeeze()284 ::Squeeze()
285 {}
286 } // end namespace itk
287 
288 #endif
289