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