/* * Ceph - scalable distributed file system * * Copyright (C) 2015 Red Hat, Inc * * This is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License version 2.1, as published by the Free Software * Foundation. See file COPYING. * */ #ifndef CEPH_COMPACT_MAP_H #define CEPH_COMPACT_MAP_H #include template class compact_map_base { protected: Map *map; void alloc_internal() { if (!map) map = new Map; } void free_internal() { if (map) { delete map; map = 0; } } template class const_iterator_base { const compact_map_base *map; It it; const_iterator_base() : map(0) { } const_iterator_base(const compact_map_base* m) : map(m) { } const_iterator_base(const compact_map_base *m, const It& i) : map(m), it(i) { } friend class compact_map_base; friend class iterator_base; public: const_iterator_base(const const_iterator_base& o) { map = o.map; it = o.it; } bool operator==(const const_iterator_base& o) const { return (map == o.map) && (!map->map || it == o.it); } bool operator!=(const const_iterator_base& o) const { return !(*this == o);; } const_iterator_base& operator=(const const_iterator_base& o) { map = o.map; it = o.it; return *this; } const_iterator_base& operator++() { ++it; return *this; } const_iterator_base& operator--() { --it; return *this; } const std::pair& operator*() { return *it; } const std::pair* operator->() { return it.operator->(); } }; template class iterator_base { private: const compact_map_base* map; It it; iterator_base() : map(0) { } iterator_base(compact_map_base* m) : map(m) { } iterator_base(compact_map_base* m, const It& i) : map(m), it(i) { } friend class compact_map_base; public: iterator_base(const iterator_base& o) { map = o.map; it = o.it; } bool operator==(const iterator_base& o) const { return (map == o.map) && (!map->map || it == o.it); } bool operator!=(const iterator_base& o) const { return !(*this == o);; } iterator_base& operator=(const iterator_base& o) { map = o.map; it = o.it; return *this; } iterator_base& operator++() { ++it; return *this; } iterator_base operator++(int) { iterator_base tmp = *this; ++it; return tmp; } iterator_base& operator--() { --it; return *this; } std::pair& operator*() { return *it; } std::pair* operator->() { return it.operator->(); } operator const_iterator_base() const { return const_iterator_base(map, it); } }; public: class iterator : public iterator_base { public: iterator() { } iterator(const iterator_base& o) : iterator_base(o) { } iterator(compact_map_base* m) : iterator_base(m) { } iterator(compact_map_base* m, const typename Map::iterator& i) : iterator_base(m, i) { } }; class const_iterator : public const_iterator_base { public: const_iterator() { } const_iterator(const iterator_base& o) : const_iterator_base(o) { } const_iterator(const compact_map_base* m) : const_iterator_base(m) { } const_iterator(const compact_map_base* m, const typename Map::const_iterator& i) : const_iterator_base(m, i) { } }; class reverse_iterator : public iterator_base { public: reverse_iterator() { } reverse_iterator(const iterator_base& o) : iterator_base(o) { } reverse_iterator(compact_map_base* m) : iterator_base(m) { } reverse_iterator(compact_map_base* m, const typename Map::reverse_iterator& i) : iterator_base(m, i) { } }; class const_reverse_iterator : public const_iterator_base { public: const_reverse_iterator() { } const_reverse_iterator(const iterator_base& o) : iterator_base(o) { } const_reverse_iterator(const compact_map_base* m) : const_iterator_base(m) { } const_reverse_iterator(const compact_map_base* m, const typename Map::const_reverse_iterator& i) : const_iterator_base(m, i) { } }; compact_map_base() : map(0) {} compact_map_base(const compact_map_base& o) : map(0) { if (o.map) { alloc_internal(); *map = *o.map; } } ~compact_map_base() { delete map; } bool empty() const { return !map || map->empty(); } size_t size() const { return map ? map->size() : 0; } bool operator==(const compact_map_base& o) const { return (empty() && o.empty()) || (map && o.map && *map == *o.map); } bool operator!=(const compact_map_base& o) const { return !(*this == o); } size_t count (const Key& k) const { return map ? map->count(k) : 0; } void erase (iterator p) { if (map) { assert(this == p.map); map->erase(p.it); if (map->empty()) free_internal(); } } size_t erase (const Key& k) { if (!map) return 0; size_t r = map->erase(k); if (map->empty()) free_internal(); return r; } void clear() { free_internal(); } void swap(compact_map_base& o) { Map *tmp = map; map = o.map; o.map = tmp; } compact_map_base& operator=(const compact_map_base& o) { if (o.map) { alloc_internal(); *map = *o.map; } else free_internal(); return *this; } iterator insert(const std::pair& val) { alloc_internal(); return iterator(this, map->insert(val)); } iterator begin() { if (!map) return iterator(this); return iterator(this, map->begin()); } iterator end() { if (!map) return iterator(this); return iterator(this, map->end()); } reverse_iterator rbegin() { if (!map) return reverse_iterator(this); return reverse_iterator(this, map->rbegin()); } reverse_iterator rend() { if (!map) return reverse_iterator(this); return reverse_iterator(this, map->rend()); } iterator find(const Key& k) { if (!map) return iterator(this); return iterator(this, map->find(k)); } iterator lower_bound(const Key& k) { if (!map) return iterator(this); return iterator(this, map->lower_bound(k)); } iterator upper_bound(const Key& k) { if (!map) return iterator(this); return iterator(this, map->upper_bound(k)); } const_iterator begin() const { if (!map) return const_iterator(this); return const_iterator(this, map->begin()); } const_iterator end() const { if (!map) return const_iterator(this); return const_iterator(this, map->end()); } const_reverse_iterator rbegin() const { if (!map) return const_reverse_iterator(this); return const_reverse_iterator(this, map->rbegin()); } const_reverse_iterator rend() const { if (!map) return const_reverse_iterator(this); return const_reverse_iterator(this, map->rend()); } const_iterator find(const Key& k) const { if (!map) return const_iterator(this); return const_iterator(this, map->find(k)); } const_iterator lower_bound(const Key& k) const { if (!map) return const_iterator(this); return const_iterator(this, map->lower_bound(k)); } const_iterator upper_bound(const Key& k) const { if (!map) return const_iterator(this); return const_iterator(this, map->upper_bound(k)); } void encode(bufferlist &bl) const { if (map) ::encode(*map, bl); else ::encode((uint32_t)0, bl); } void encode(bufferlist &bl, uint64_t features) const { if (map) ::encode(*map, bl, features); else ::encode((uint32_t)0, bl); } void decode(bufferlist::iterator& p) { uint32_t n; ::decode(n, p); if (n > 0) { alloc_internal(); ::decode_nohead(n, *map, p); } else free_internal(); } }; template inline void encode(const compact_map_base& m, bufferlist& bl) { m.encode(bl); } template inline void encode(const compact_map_base& m, bufferlist& bl, uint64_t features) { m.encode(bl, features); } template inline void decode(compact_map_base& m, bufferlist::iterator& p) { m.decode(p); } template class compact_map : public compact_map_base > { public: T& operator[](const Key& k) { this->alloc_internal(); return (*(this->map))[k]; } }; template inline std::ostream& operator<<(std::ostream& out, const compact_map& m) { out << "{"; for (typename compact_map::const_iterator it = m.begin(); it != m.end(); ++it) { if (it != m.begin()) out << ","; out << it->first << "=" << it->second; } out << "}"; return out; } template class compact_multimap : public compact_map_base > { }; template inline std::ostream& operator<<(std::ostream& out, const compact_multimap& m) { out << "{{"; for (typename compact_map::const_iterator it = m.begin(); !it.end(); ++it) { if (it != m.begin()) out << ","; out << it->first << "=" << it->second; } out << "}}"; return out; } #endif