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 itkMapContainer_h
19 #define itkMapContainer_h
20 
21 #include "itkObject.h"
22 #include "itkObjectFactory.h"
23 
24 #include <map>
25 
26 namespace itk
27 {
28 /** \class MapContainer
29  * \brief A wrapper of the STL "map" container.
30  *
31  * Define a front-end to the STL "map" container that conforms to the
32  * IndexedContainerInterface.  This is a full-fleged Object, so
33  * there are events, modification time, debug, and reference count
34  * information.
35  *
36  * \tparam TElementIdentifier A type that shall be used to index the
37  * container. It must have a < operator defined for ordering.
38  *
39  * \tparam TElement The element type stored in the container.
40  *
41  * \ingroup DataRepresentation
42  * \ingroup ITKCommon
43  */
44 template< typename TElementIdentifier, typename TElement >
45 class ITK_TEMPLATE_EXPORT MapContainer:
46   public Object,
47   private std::map< TElementIdentifier, TElement >
48 {
49 public:
50   ITK_DISALLOW_COPY_AND_ASSIGN(MapContainer);
51 
52   /** Standard class type aliases. */
53   using Self = MapContainer;
54   using Superclass = Object;
55   using Pointer = SmartPointer< Self >;
56   using ConstPointer = SmartPointer< const Self >;
57 
58   /** Standard part of every itk Object. */
59   itkTypeMacro(MapContainer, Object);
60 
61   /** Save the template parameters. */
62   using ElementIdentifier = TElementIdentifier;
63   using Element = TElement;
64 
65 private:
66   /** Quick access to the STL map type that was inherited. */
67   using MapType = std::map< ElementIdentifier, Element >;
68   using MapIterator = typename MapType::iterator;
69   using MapConstIterator = typename MapType::const_iterator;
70   using MapKeyCompareType = typename MapType::key_compare;
71 
72 public:
73   /** Provide pass-through constructors corresponding to all the STL
74    * map constructors.  These are for internal use only since this is also
75    * an Object which must be constructed through the "New()" routine. */
MapContainer()76   MapContainer():MapType() {}
MapContainer(const MapKeyCompareType & comp)77   MapContainer(const MapKeyCompareType & comp):MapType(comp) {}
78   //  MapContainer(const Self& r):MapType(r) {}
79   template< typename TInputIterator >
MapContainer(TInputIterator first,TInputIterator last)80   MapContainer(TInputIterator first, TInputIterator last):MapType(first, last) {}
81   template< typename TInputIterator >
MapContainer(TInputIterator first,TInputIterator last,const MapKeyCompareType & comp)82   MapContainer(TInputIterator first, TInputIterator last, const MapKeyCompareType & comp):
83     MapType(first, last, comp) {}
84 
85   /** Method for creation through the object factory. */
86   itkNewMacro(Self);
87 
88   /** This type is provided to adapt this container as an STL container */
89   using STLContainerType = MapType;
90 
91   /** Cast the container to a STL container type */
CastToSTLContainer()92   STLContainerType & CastToSTLContainer() ITK_NOEXCEPT
93   {
94     return *this;
95   }
96 
97   /** Cast the container to a const STL container type */
CastToSTLConstContainer()98   const STLContainerType & CastToSTLConstContainer() const ITK_NOEXCEPT
99   {
100     return *this;
101   }
102 
103   using STLContainerType::begin;
104   using STLContainerType::end;
105   using STLContainerType::rbegin;
106   using STLContainerType::rend;
107 
108   using STLContainerType::empty;
109   using STLContainerType::size;
110   using STLContainerType::max_size;
111 
112   using STLContainerType::operator[];
113 
114   using STLContainerType::insert;
115   using STLContainerType::erase;
116   using STLContainerType::swap;
117   using STLContainerType::clear;
118 
119   using STLContainerType::key_comp;
120   using STLContainerType::value_comp;
121 
122   using STLContainerType::find;
123   using STLContainerType::count;
124   using STLContainerType::lower_bound;
125   using STLContainerType::upper_bound;
126   using STLContainerType::equal_range;
127 
128   using STLContainerType::get_allocator;
129 
130   using typename STLContainerType::key_type;
131   using typename STLContainerType::mapped_type;
132   using typename STLContainerType::value_type;
133   using typename STLContainerType::key_compare;
134   using typename STLContainerType::value_compare;
135   using typename STLContainerType::allocator_type;
136   using typename STLContainerType::reference;
137   using typename STLContainerType::const_reference;
138   using typename STLContainerType::iterator;
139   using typename STLContainerType::const_iterator;
140   using typename STLContainerType::size_type;
141   using typename STLContainerType::difference_type;
142   using typename STLContainerType::pointer;
143   using typename STLContainerType::const_pointer;
144   using typename STLContainerType::reverse_iterator;
145   using typename STLContainerType::const_reverse_iterator;
146 
147   /** Declare iterators to container. */
148   class Iterator;
149   class ConstIterator;
150   friend class Iterator;
151   friend class ConstIterator;
152 
153   /** \class Iterator
154    * \brief The non-const iterator type for the map.
155    * \ingroup ITKCommon
156    */
157   class Iterator
158   {
159 public:
160     using iterator_category = typename MapIterator::iterator_category;
161     using value_type = typename MapIterator::value_type;
162     using difference_type = typename MapIterator::difference_type;
163     using pointer = typename MapIterator::pointer;
164     using reference = typename MapIterator::reference;
165 
166     Iterator() = default;
Iterator(const Iterator & i)167     Iterator(const Iterator & i):m_Iter(i.m_Iter) {}
Iterator(const MapIterator & i)168     Iterator(const MapIterator & i):m_Iter(i) {}
169     Iterator & operator=(const Iterator & r ) { m_Iter = r.m_Iter; return *this; }
170 
171     Iterator & operator*()    { return *this; }
172     Iterator * operator->()   { return this; }
173     Iterator & operator++()   { ++m_Iter; return *this; }
174     Iterator operator++(int) { Iterator temp(*this);  ++m_Iter; return temp; }
175     Iterator & operator--()   { --m_Iter; return *this; }
176     Iterator operator--(int) { Iterator temp(*this); --m_Iter; return temp; }
177 
178     bool operator==(const Iterator & r) const { return m_Iter == r.m_Iter; }
179     bool operator!=(const Iterator & r) const { return m_Iter != r.m_Iter; }
180     bool operator==(const ConstIterator & r) const { return m_Iter == r.m_Iter; }
181     bool operator!=(const ConstIterator & r) const { return m_Iter != r.m_Iter; }
182 
183     /** Get the index into the MapContainer associated with this iterator.   */
Index()184     ElementIdentifier Index() const { return m_Iter->first; }
185 
186     /** Get the value at this iterator's location in the MapContainer.   */
Value()187     Element & Value() { return m_Iter->second; }
188 
189 private:
190     MapIterator m_Iter;
191     friend class ConstIterator;
192   };
193 
194   /** \class ConstIterator
195    * \brief The const iterator type for the map.
196    * \ingroup ITKCommon
197    */
198   class ConstIterator
199   {
200 public:
201     using iterator_category = typename MapConstIterator::iterator_category;
202     using value_type = typename MapConstIterator::value_type;
203     using difference_type = typename MapConstIterator::difference_type;
204     using pointer = typename MapConstIterator::pointer;
205     using reference = typename MapConstIterator::reference;
206 
207     ConstIterator() = default;
ConstIterator(const MapConstIterator & ci)208     ConstIterator(const MapConstIterator & ci):m_Iter(ci) {}
ConstIterator(const Iterator & r)209     ConstIterator(const Iterator & r) : m_Iter( r.m_Iter ) {}
210     ConstIterator & operator=(const ConstIterator & r ) { m_Iter = r.m_Iter; return *this; }
211 
212     ConstIterator & operator*()    { return *this; }
213     ConstIterator * operator->()   { return this; }
214     ConstIterator & operator++()   { ++m_Iter; return *this; }
215     ConstIterator operator++(int) { ConstIterator temp(*this);  ++m_Iter; return temp; }
216     ConstIterator & operator--()   { --m_Iter; return *this; }
217     ConstIterator operator--(int) { ConstIterator temp(*this); --m_Iter; return temp; }
218 
219     bool operator==(const Iterator & r) const { return m_Iter == r.m_Iter; }
220     bool operator!=(const Iterator & r) const { return m_Iter != r.m_Iter; }
221     bool operator==(const ConstIterator & r) const { return m_Iter == r.m_Iter; }
222     bool operator!=(const ConstIterator & r) const { return m_Iter != r.m_Iter; }
223 
224     /** Get the index into the MapContainer associated with this iterator.   */
Index()225     ElementIdentifier Index() const { return m_Iter->first; }
226 
227     /** Get the value at this iterator's location in the MapContainer.   */
Value()228     const Element & Value() const { return m_Iter->second; }
229 
230 private:
231     MapConstIterator m_Iter;
232     friend class Iterator;
233   };
234 
235   /* Declare the public interface routines. */
236 
237   /**
238    * Get a reference to the element at the given index.
239    * If the index does not exist, it is created automatically.
240    *
241    * It is assumed that the value of the element is modified through the
242    * reference.
243    */
244   Element & ElementAt(ElementIdentifier);
245 
246   /**
247    * Get a reference to the element at the given index.
248    *
249    */
250   const Element & ElementAt(ElementIdentifier) const;
251 
252   /**
253    * Get a reference to the element at the given index.
254    * If the index does not exist, it is created automatically.
255    *
256    * It is assumed that the value of the element is modified through the
257    * reference.
258    */
259   Element & CreateElementAt(ElementIdentifier);
260 
261   /**
262    * Get the element at the specified index.  There is no check for
263    * existence performed.
264    */
265   Element GetElement(ElementIdentifier) const;
266 
267   /**
268    * Set the given index value to the given element.  If the index doesn't
269    * exist, it is automatically created.
270    */
271   void SetElement(ElementIdentifier, Element);
272 
273   /**
274    * Set the given index value to the given element.  If the index doesn't
275    * exist, it is automatically created.
276    */
277   void InsertElement(ElementIdentifier, Element);
278 
279   /**
280    * Check if the STL map has an entry corresponding to the given index.
281    * The count will be either 1 or 0.
282    */
283   bool IndexExists(ElementIdentifier) const;
284 
285   /**
286    * If the given index doesn't exist in the map, return false.
287    * Otherwise, set the element through the pointer (if it isn't null), and
288    * return true.
289    */
290   bool GetElementIfIndexExists(ElementIdentifier, Element *) const;
291 
292   /**
293    * The map will create an entry for a given index through the indexing
294    * operator.  Whether or not it is created, it will be assigned to the
295    * default element.
296    */
297   void CreateIndex(ElementIdentifier);
298 
299   /**
300    * Delete the entry in the STL map corresponding to the given identifier.
301    * If the entry does not exist, nothing happens.
302    */
303   void DeleteIndex(ElementIdentifier);
304 
305   /**
306    * Get a begin const iterator for the map.
307    */
308   ConstIterator Begin() const;
309 
310   /**
311    * Get an end const iterator for the map.
312    */
313   ConstIterator End() const;
314 
315   /**
316    * Get a begin const iterator for the map.
317    */
318   Iterator Begin();
319 
320   /**
321    * Get an end const iterator for the map.
322    */
323   Iterator End();
324 
325   /**
326    * Get the number of elements currently stored in the map.
327    */
328   ElementIdentifier Size() const;
329 
330   /**
331    * Tell the container to allocate enough memory to allow at least
332    * as many elements as the size given to be stored.  This is NOT
333    * guaranteed to actually allocate any memory, but is useful if the
334    * implementation of the container allocates contiguous storage.
335    */
336   void Reserve(ElementIdentifier);
337 
338   /**
339    * Tell the container to try to minimize its memory usage for storage of
340    * the current number of elements.  This is NOT guaranteed to decrease
341    * memory usage.
342    */
343   void Squeeze();
344 
345   /**
346    * Tell the container to release any memory it may have allocated and
347    * return itself to its initial state.
348    */
349   void Initialize();
350 };
351 } // end namespace itk
352 
353 #ifndef ITK_MANUAL_INSTANTIATION
354 #include "itkMapContainer.hxx"
355 #endif
356 
357 #endif
358