1 /* 2 * 3 * Copyright (C) 2009-2019, OFFIS e.V. 4 * All rights reserved. See COPYRIGHT file for details. 5 * 6 * This software and supporting documentation were developed by 7 * 8 * OFFIS e.V. 9 * R&D Division Health 10 * Escherweg 2 11 * D-26121 Oldenburg, Germany 12 * 13 * 14 * Module: ofstd 15 * 16 * Author: Uli Schlachter 17 * 18 * Purpose: Defines a template map class with interfaces similar to the C++ 19 * Standard 20 * 21 */ 22 23 #ifndef OFMAP_H 24 #define OFMAP_H 25 26 #include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ 27 28 #include "dcmtk/ofstd/ofutil.h" // for OFPair 29 30 #ifdef HAVE_STL_MAP 31 // it is possible to use the standard template library map class since the 32 // interface is nearly identical. 33 #include <map> 34 #define OFMap std::map 35 #else 36 37 #include "dcmtk/ofstd/oftypes.h" 38 #include "dcmtk/ofstd/ofcast.h" 39 #include "dcmtk/ofstd/oflist.h" 40 41 #ifndef HAVE_CLASS_TEMPLATE 42 #error Your C++ compiler cannot handle class templates: 43 #endif 44 45 /** associative container class. This class is a subset of std::map. 46 */ 47 template<typename K, typename V> class OFMap 48 { 49 public: 50 51 /** the type of values saved in this map */ 52 typedef OFPair<const K, V> value_type; 53 54 protected: 55 56 /// @todo using a list as base is slooooow 57 OFList<value_type> values_; 58 59 public: 60 61 /** iterator class for OFMap. You can modify elements through this 62 * iterator's ->first and ->second properties. 63 */ 64 typedef OFListIterator(value_type) iterator; 65 66 /** constant iterator class for OFMap. You can read the elements, but you may 67 * not modify them. 68 */ 69 typedef OFListConstIterator(value_type) const_iterator; 70 71 /** default constructor */ OFMap()72 OFMap() : values_() { } 73 74 /** assignment operator */ 75 OFMap& operator=(const OFMap& other) 76 { 77 if (this == &other) 78 return *this; 79 80 clear(); 81 82 for (const_iterator it = other.begin(); 83 it != other.end(); it++) 84 insert(*it); 85 86 return *this; 87 } 88 89 /** index operator. You can use this to add new elements to the map. 90 * Beware: Don't use this for checking if a given key is already used in 91 * the map, use find() != end() for this job! 92 * @param key the key you want to access 93 * @return reference to the value saved under the given key. 94 */ 95 V& operator[](const K& key) 96 { 97 iterator it = find(key); 98 if (it == end()) 99 { 100 it = insert(value_type(key, V())).first; 101 } 102 103 return it->second; 104 } 105 106 /** returns iterator pointing to the first element of this map 107 * @return iterator pointing to the first element of this map 108 */ begin()109 iterator begin() { return values_.begin(); } 110 111 /** returns iterator pointer after the last element of this map 112 * @return iterator pointer after the last element of this map 113 */ end()114 iterator end() { return values_.end(); } 115 116 /** returns constant iterator pointing to the first element of this map 117 * @return constant iterator pointing to the first element of this map 118 */ begin()119 const_iterator begin() const { return values_.begin(); } 120 121 /** returns constant iterator pointer after the last element of this map 122 * @return constant iterator pointer after the last element of this map 123 */ end()124 const_iterator end() const { return values_.end(); } 125 126 /** looks up the given key in this map 127 * @param key the key to look for 128 * @return iterator for that key to end() 129 */ find(const K & key)130 iterator find(const K& key) 131 { 132 iterator it = begin(); 133 while (it != end()) 134 { 135 if (it->first == key) 136 break; 137 it++; 138 } 139 140 return it; 141 } 142 143 /** looks up the given key in this map 144 * @param key the key to look for 145 * @return constant iterator for that key to end() 146 */ find(const K & key)147 const_iterator find(const K& key) const 148 { 149 const_iterator it = begin(); 150 while (it != end()) 151 { 152 if (it->first == key) 153 break; 154 it++; 155 } 156 157 return it; 158 } 159 160 /** returns whether this map is empty (i.e.\ whether its size is 0) 161 * @return OFTrue if this map is empty, OFFalse otherwise 162 */ empty()163 OFBool empty() const { return values_.size() == 0; } 164 165 /** returns the number of elements saved in this map 166 * @return the number of elements saved in this map 167 */ size()168 size_t size() const { return values_.size(); } 169 170 /** removes all elements from this map */ clear()171 void clear() { values_.clear(); } 172 173 /** removes all elements in the given range from this map 174 * @param first the first element to remove 175 * @param last the first element NOT to remove 176 */ erase(const iterator & first,const iterator & last)177 void erase(const iterator& first, const iterator& last) 178 { 179 values_.erase(first, last); 180 } 181 182 /** removes the element to which the given iterator points to 183 * @param elem the element to remove 184 */ erase(const iterator & elem)185 void erase(const iterator& elem) 186 { 187 values_.erase(elem); 188 } 189 190 /** removes the element with the given key from this map 191 * @return the number of elements removed (0 or 1) 192 */ erase(const K & key)193 int erase(const K& key) 194 { 195 iterator it = find(key); 196 if (it == end()) 197 return 0; 198 199 values_.erase(it); 200 return 1; 201 } 202 203 /** inserts a new element into the map, but does not overwrite existing 204 * elements 205 * @param val the value to insert 206 * @return a pair of an iterator and a boolean. The iterator always points 207 * to the element which got val's key. The boolean is true if val was 208 * inserted, false otherwise. 209 */ insert(const value_type & val)210 OFPair<iterator, bool> insert(const value_type& val) 211 { 212 // If value already exists, return it 213 OFListIterator(value_type) it = find(val.first); 214 if (it != end()) 215 return OFMake_pair(it, false); 216 217 // Sorted insertion 218 it = begin(); 219 while ( (it != end()) && (val.first > it->first) ) 220 it++; 221 if (it == end()) 222 it = values_.insert(values_.end(), val); 223 else 224 { 225 // Insert at current position and rewind iterator 226 // to the inserted element 227 values_.insert(it, val); 228 it--; 229 } 230 231 return OFMake_pair(it, true); 232 } 233 234 /** swaps the contents of the two maps. The time complexity of this 235 * function should be constant. 236 * @param s map to swap with 237 */ swap(OFMap<K,V> & s)238 void swap(OFMap<K, V>& s) 239 { 240 OFList<value_type> own_values = values_; 241 values_ = s.values_; 242 s.values_ = own_values; 243 } 244 }; 245 246 #endif 247 #endif 248