1 /* 2 * Copyright (C) 2009-2012 Codership Oy <info@codership.com> 3 */ 4 5 /*! 6 * @file map.hpp 7 * 8 * This file contains templates that are thin wrappers for std::map 9 * and std::multimap with some extra functionality. 10 */ 11 12 #ifndef GCOMM_MAP_HPP 13 #define GCOMM_MAP_HPP 14 15 #include "gu_serialize.hpp" 16 17 #include <utility> 18 #include <iterator> 19 #include <map> 20 21 #include "gcomm/exception.hpp" 22 #include "gcomm/types.hpp" 23 24 namespace gcomm 25 { 26 template<typename K, typename V, typename C> 27 class MapBase 28 { 29 typedef C MapType; 30 31 public: 32 33 typedef typename MapType::iterator iterator; 34 typedef typename MapType::const_iterator const_iterator; 35 typedef typename MapType::reverse_iterator reverse_iterator; 36 typedef typename MapType::const_reverse_iterator const_reverse_iterator; 37 typedef typename MapType::value_type value_type; 38 typedef typename MapType::const_reference const_reference; 39 typedef typename MapType::key_type key_type; 40 typedef typename MapType::mapped_type mapped_type; 41 42 protected: 43 44 MapType map_; 45 public: 46 MapBase()47 MapBase() : map_() {} 48 ~MapBase()49 virtual ~MapBase() {} 50 begin()51 iterator begin() { return map_.begin(); } 52 end()53 iterator end() { return map_.end(); } 54 find(const K & k)55 iterator find(const K& k) { return map_.find(k); } 56 find_checked(const K & k)57 iterator find_checked(const K& k) 58 { 59 iterator ret = map_.find(k); 60 if (ret == map_.end()) 61 { 62 gu_throw_fatal << "element " << k << " not found"; 63 } 64 return ret; 65 } 66 lower_bound(const K & k)67 iterator lower_bound(const K& k) { return map_.lower_bound(k); } 68 begin() const69 const_iterator begin() const { return map_.begin(); } 70 end() const71 const_iterator end() const { return map_.end(); } 72 rbegin() const73 const_reverse_iterator rbegin() const { return map_.rbegin(); } 74 rend() const75 const_reverse_iterator rend() const { return map_.rend(); } 76 find(const K & k) const77 const_iterator find(const K& k) const { return map_.find(k); } 78 find_checked(const K & k) const79 const_iterator find_checked(const K& k) const 80 { 81 const_iterator ret = map_.find(k); 82 if (ret == map_.end()) 83 { 84 gu_throw_fatal << "element " << k << " not found"; 85 } 86 return ret; 87 } 88 operator [](const key_type & k)89 mapped_type& operator[](const key_type& k) { return map_[k]; } 90 erase(iterator i)91 void erase(iterator i) { map_.erase(i); } 92 erase(iterator i,iterator j)93 void erase(iterator i, iterator j) { map_.erase(i, j); } 94 erase(const K & k)95 void erase(const K& k) { map_.erase(k); } 96 clear()97 void clear() { map_.clear(); } 98 size() const99 size_t size() const { return map_.size(); } 100 empty() const101 bool empty() const { return map_.empty(); } 102 serialize(gu::byte_t * const buf,size_t const buflen,size_t offset) const103 size_t serialize(gu::byte_t* const buf, 104 size_t const buflen, 105 size_t offset) const 106 { 107 gu_trace(offset = gu::serialize4( 108 static_cast<uint32_t>(size()), buf, buflen, offset)); 109 for (const_iterator i = map_.begin(); i != map_.end(); ++i) 110 { 111 gu_trace(offset = key(i).serialize(buf, buflen, offset)); 112 gu_trace(offset = value(i).serialize(buf, buflen, offset)); 113 } 114 return offset; 115 } 116 unserialize(const gu::byte_t * buf,size_t const buflen,size_t offset)117 size_t unserialize(const gu::byte_t* buf, 118 size_t const buflen, 119 size_t offset) 120 { 121 uint32_t len; 122 // Clear map in case this object is reused 123 map_.clear(); 124 125 gu_trace(offset = gu::unserialize4(buf, buflen, offset, len));; 126 127 for (uint32_t i = 0; i < len; ++i) 128 { 129 K k; 130 V v; 131 gu_trace(offset = k.unserialize(buf, buflen, offset)); 132 gu_trace(offset = v.unserialize(buf, buflen, offset)); 133 if (map_.insert(std::make_pair(k, v)).second == false) 134 { 135 gu_throw_fatal << "Failed to unserialize map"; 136 } 137 } 138 return offset; 139 } 140 serial_size() const141 size_t serial_size() const 142 { 143 return sizeof(uint32_t) + size()*(K::serial_size() + V::serial_size()); 144 } 145 operator ==(const MapBase & other) const146 bool operator==(const MapBase& other) const 147 { 148 return (map_ == other.map_); 149 } 150 operator !=(const MapBase & other) const151 bool operator!=(const MapBase& other) const 152 { 153 return !(map_ == other.map_); 154 } 155 key(const_iterator i)156 static const K& key(const_iterator i) 157 { 158 return i->first; 159 } 160 key(iterator i)161 static const K& key(iterator i) 162 { 163 return i->first; 164 } 165 value(const_iterator i)166 static const V& value(const_iterator i) 167 { 168 return i->second; 169 } 170 value(iterator i)171 static V& value(iterator i) 172 { 173 return i->second; 174 } 175 key(const value_type & vt)176 static const K& key(const value_type& vt) 177 { 178 return vt.first; 179 } 180 value(value_type & vt)181 static V& value(value_type& vt) 182 { 183 return vt.second; 184 } 185 value(const value_type & vt)186 static const V& value(const value_type& vt) 187 { 188 return vt.second; 189 } 190 }; 191 192 // @todo For some reason map key must be declared in gcomm namespace 193 // in order this to work. Find out the reason why and fix. 194 template <typename K, typename V> operator <<(std::ostream & os,const std::pair<K,V> & p)195 std::ostream& operator<<(std::ostream& os, const std::pair<K, V>& p) 196 { 197 return (os << "\t" << p.first << "," << p.second << "\n"); 198 } 199 200 template <typename K, typename V, typename C> operator <<(std::ostream & os,const MapBase<K,V,C> & map)201 std::ostream& operator<<(std::ostream& os, const MapBase<K, V, C>& map) 202 { 203 std::copy(map.begin(), map.end(), 204 std::ostream_iterator<const std::pair<const K, V> >(os, "")); 205 return os; 206 } 207 208 209 template <typename K, typename V, typename C = std::map<K, V> > 210 class Map : public MapBase<K, V, C> 211 { 212 public: 213 typedef typename MapBase<K, V, C>::iterator iterator; insert(const std::pair<K,V> & p)214 std::pair<iterator, bool> insert(const std::pair<K, V>& p) 215 { 216 return MapBase<K, V, C>::map_.insert(p); 217 } 218 insert(iterator pos,const std::pair<K,V> & p)219 iterator insert(iterator pos, const std::pair<K, V>& p) 220 { 221 return MapBase<K, V, C>::map_.insert(pos, p); 222 } 223 224 template <class InputIterator> insert(InputIterator first,InputIterator last)225 void insert(InputIterator first, InputIterator last) 226 { 227 MapBase<K, V, C>::map_.insert(first, last); 228 } 229 insert_unique(const typename MapBase<K,V,C>::value_type & p)230 iterator insert_unique(const typename MapBase<K, V, C>::value_type& p) 231 { 232 std::pair<iterator, bool> ret = MapBase<K, V, C>::map_.insert(p); 233 if (false == ret.second) 234 { 235 gu_throw_fatal << "duplicate entry " 236 << "key=" << MapBase<K, V, C>::key(p) << " " 237 << "value=" << MapBase<K, V, C>::value(p) << " " 238 << "map=" << *this; 239 } 240 return ret.first; 241 } 242 243 }; 244 245 246 247 248 template <typename K, typename V, typename C = std::multimap<K, V> > 249 class MultiMap : public MapBase<K, V, C> 250 { 251 public: 252 typedef typename MapBase<K, V, C>::iterator iterator; 253 typedef typename MapBase<K, V, C>::const_iterator const_iterator; 254 typedef typename MapBase<K, V, C>::value_type value_type; 255 typedef typename MapBase<K, V, C>::const_reference const_reference; 256 insert(const std::pair<K,V> & p)257 iterator insert(const std::pair<K, V>& p) 258 { 259 return MapBase<K, V, C>::map_.insert(p); 260 } 261 insert(iterator position,const value_type & vt)262 iterator insert(iterator position, const value_type& vt) 263 { 264 return MapBase<K, V, C>::map_.insert(position, vt); 265 } 266 equal_range(const K & k) const267 std::pair<const_iterator, const_iterator> equal_range(const K& k) const 268 { 269 return MapBase<K, V, C>::map_.equal_range(k); 270 } 271 }; 272 } 273 #endif /* GCOMM_MAP_HPP */ 274