diff options
author | Attila Molnar <attilamolnar@hush.com> | 2014-12-15 17:36:20 +0100 |
---|---|---|
committer | Attila Molnar <attilamolnar@hush.com> | 2014-12-15 17:36:20 +0100 |
commit | 3eed53a5bb3b8460c6732237f690fe623d70f167 (patch) | |
tree | 9b2b1ba99a7edda6d42cea01520b7ad5186c2958 /include/flat_map.h | |
parent | 56af4909b89d3edfe919fe28178c18dcaa9cee47 (diff) |
Add flat_[multi]{map,set} containers
Diffstat (limited to 'include/flat_map.h')
-rw-r--r-- | include/flat_map.h | 383 |
1 files changed, 383 insertions, 0 deletions
diff --git a/include/flat_map.h b/include/flat_map.h new file mode 100644 index 000000000..bef1404e4 --- /dev/null +++ b/include/flat_map.h @@ -0,0 +1,383 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * Copyright (C) 2014 Attila Molnar <attilamolnar@hush.com> + * + * This file is part of InspIRCd. InspIRCd is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + + +#pragma once + +#include <vector> + +namespace insp +{ + +namespace detail +{ + +template <typename T, typename Comp> +class map_pair_compare : public Comp +{ + typedef T value_type; + typedef typename value_type::first_type key_type; + + public: + bool operator()(const value_type& x, const value_type& y) const + { + return Comp::operator()(x.first, y.first); + } + + bool operator()(const value_type& x, const key_type& y) const + { + return Comp::operator()(x.first, y); + } + + bool operator()(const key_type& x, const value_type& y) const + { + return Comp::operator()(x, y.first); + } +}; + +template <typename Val, typename Comp> +class map_value_compare : public std::binary_function<Val, Val, bool> +{ + public: + // Constructor should be private + + bool operator()(const Val& x, const Val& y) const + { + Comp c; + return c(x.first, y.first); + } +}; + +template <typename T, typename Comp, typename Key = T, typename ElementComp = Comp> +class flat_map_base +{ + protected: + typedef std::vector<T> storage_type; + storage_type vect; + + public: + typedef typename storage_type::iterator iterator; + typedef typename storage_type::const_iterator const_iterator; + typedef typename storage_type::reverse_iterator reverse_iterator; + typedef typename storage_type::const_reverse_iterator const_reverse_iterator; + + typedef typename storage_type::size_type size_type; + typedef typename storage_type::difference_type difference_type; + typedef Key key_type; + typedef T value_type; + + typedef Comp key_compare; + typedef ElementComp value_compare; + + flat_map_base() { } + + flat_map_base(const flat_map_base& other) + : vect(other.vect) + { + } + + size_type size() const { return vect.size(); } + bool empty() const { return vect.empty(); } + size_type capacity() const { return vect.capacity(); } + size_type max_size() const { return vect.max_size(); } + + void clear() { vect.clear(); } + void reserve(size_type n) { vect.reserve(n); } + + iterator begin() { return vect.begin(); } + iterator end() { return vect.end(); } + reverse_iterator rbegin() { return vect.rbegin(); } + reverse_iterator rend() { return vect.rend(); } + + const_iterator begin() const { return vect.begin(); } + const_iterator end() const { return vect.end(); } + const_reverse_iterator rbegin() const { return vect.rbegin(); } + const_reverse_iterator rend() const { return vect.rend(); } + + key_compare key_comp() const { return Comp(); } + + iterator erase(iterator it) { return vect.erase(it); } + iterator erase(iterator first, iterator last) { return vect.erase(first, last); } + size_type erase(const key_type& x) + { + size_type n = vect.size(); + std::pair<iterator, iterator> itpair = equal_range(x); + vect.erase(itpair.first, itpair.second); + return n - vect.size(); + } + + iterator find(const key_type& x) + { + value_compare c; + iterator it = std::lower_bound(vect.begin(), vect.end(), x, c); + if ((it != vect.end()) && (!c(x, *it))) + return it; + return vect.end(); + } + + const_iterator find(const key_type& x) const + { + // Same as above but this time we return a const_iterator + value_compare c; + const_iterator it = std::lower_bound(vect.begin(), vect.end(), x, c); + if ((it != vect.end()) && (!c(x, *it))) + return it; + return vect.end(); + } + + std::pair<iterator, iterator> equal_range(const key_type& x) + { + return std::equal_range(vect.begin(), vect.end(), x, value_compare()); + } + + std::pair<const_iterator, const_iterator> equal_range(const key_type& x) const + { + return std::equal_range(vect.begin(), vect.end(), x, value_compare()); + } + + iterator lower_bound(const key_type& x) + { + return std::lower_bound(vect.begin(), vect.end(), x, value_compare()); + } + + const_iterator lower_bound(const key_type& x) const + { + return std::lower_bound(vect.begin(), vect.end(), x, value_compare()); + } + + iterator upper_bound(const key_type& x) + { + return std::upper_bound(vect.begin(), vect.end(), x, value_compare()); + } + + const_iterator upper_bound(const key_type& x) const + { + return std::upper_bound(vect.begin(), vect.end(), x, value_compare()); + } + + size_type count(const key_type& x) const + { + std::pair<const_iterator, const_iterator> itpair = equal_range(x); + return std::distance(itpair.first, itpair.second); + } + + protected: + std::pair<iterator, bool> insert_single(const value_type& x) + { + bool inserted = false; + + value_compare c; + iterator it = std::lower_bound(vect.begin(), vect.end(), x, c); + if ((it == vect.end()) || (c(x, *it))) + { + inserted = true; + it = vect.insert(it, x); + } + return std::make_pair(it, inserted); + } + + iterator insert_multi(const value_type& x) + { + iterator it = std::lower_bound(vect.begin(), vect.end(), x, value_compare()); + return vect.insert(it, x); + } +}; + +} // namespace detail + +template <typename T, typename Comp = std::less<T> > +class flat_set : public detail::flat_map_base<T, Comp> +{ + typedef detail::flat_map_base<T, Comp> base_t; + + public: + typedef typename base_t::iterator iterator; + typedef typename base_t::value_type value_type; + + flat_set() { } + + template <typename InputIterator> + flat_set(InputIterator first, InputIterator last) + { + this->insert(first, last); + } + + flat_set(const flat_set& other) + : base_t(other) + { + } + + std::pair<iterator, bool> insert(const value_type& x) + { + return this->insert_single(x); + } + + template <typename InputIterator> + void insert(InputIterator first, InputIterator last) + { + for (; first != last; ++first) + this->insert_single(*first); + } + + void swap(flat_set& other) + { + base_t::vect.swap(other.vect); + } +}; + +template <typename T, typename Comp = std::less<T> > +class flat_multiset : public detail::flat_map_base<T, Comp> +{ + typedef detail::flat_map_base<T, Comp> base_t; + + public: + typedef typename base_t::iterator iterator; + typedef typename base_t::value_type value_type; + + flat_multiset() { } + + template <typename InputIterator> + flat_multiset(InputIterator first, InputIterator last) + { + this->insert(first, last); + } + + flat_multiset(const flat_multiset& other) + : base_t(other) + { + } + + iterator insert(const value_type& x) + { + return this->insert_multi(x); + } + + template <typename InputIterator> + void insert(InputIterator first, InputIterator last) + { + for (; first != last; ++first) + insert_multi(*first); + } + + void swap(flat_multiset& other) + { + base_t::vect.swap(other.vect); + } +}; + +template <typename T, typename U, typename Comp = std::less<T> > +class flat_map : public detail::flat_map_base<std::pair<T, U>, Comp, T, detail::map_pair_compare<std::pair<T, U>, Comp> > +{ + typedef detail::flat_map_base<std::pair<T, U>, Comp, T, detail::map_pair_compare<std::pair<T, U>, Comp> > base_t; + + public: + typedef typename base_t::iterator iterator; + typedef typename base_t::key_type key_type; + typedef typename base_t::value_type value_type; + typedef U mapped_type; + typedef typename base_t::value_compare value_compare; + + flat_map() { } + + template <typename InputIterator> + flat_map(InputIterator first, InputIterator last) + { + insert(first, last); + } + + flat_map(const flat_map& other) + : base_t(other) + { + } + + std::pair<iterator, bool> insert(const value_type& x) + { + return this->insert_single(x); + } + + template <typename InputIterator> + void insert(InputIterator first, InputIterator last) + { + for (; first != last; ++first) + this->insert_single(*first); + } + + void swap(flat_map& other) + { + base_t::vect.swap(other.vect); + } + + mapped_type& operator[](const key_type& x) + { + return insert(std::make_pair(x, mapped_type())).first->second; + } + + value_compare value_comp() const + { + return value_compare(); + } +}; + +template <typename T, typename U, typename Comp = std::less<T> > +class flat_multimap : public detail::flat_map_base<std::pair<T, U>, Comp, T, detail::map_pair_compare<std::pair<T, U>, Comp> > +{ + typedef detail::flat_map_base<std::pair<T, U>, Comp, T, detail::map_pair_compare<std::pair<T, U>, Comp> > base_t; + + public: + typedef typename base_t::iterator iterator; + typedef typename base_t::value_type value_type; + typedef U mapped_type; + typedef typename base_t::value_compare value_compare; + + flat_multimap() { } + + template <typename InputIterator> + flat_multimap(InputIterator first, InputIterator last) + { + this->insert(first, last); + } + + flat_multimap(const flat_multimap& other) + : base_t(other) + { + } + + iterator insert(const value_type& x) + { + return this->insert_multi(x); + } + + template <typename InputIterator> + void insert(InputIterator first, InputIterator last) + { + for (; first != last; ++first) + this->insert_multi(*first); + } + + void swap(flat_multimap& other) + { + base_t::vect.swap(other.vect); + } + + value_compare value_comp() const + { + return value_compare(); + } +}; + +} // namespace insp |