Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1868)

Unified Diff: base/containers/flat_sorted_container_base.h

Issue 2333253002: flat containers prototype (Closed)
Patch Set: Fixing performance bug in insert(It, It) Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: base/containers/flat_sorted_container_base.h
diff --git a/base/containers/flat_sorted_container_base.h b/base/containers/flat_sorted_container_base.h
new file mode 100644
index 0000000000000000000000000000000000000000..7043242d59c0913bed7b2f153a3e36c824636099
--- /dev/null
+++ b/base/containers/flat_sorted_container_base.h
@@ -0,0 +1,265 @@
+// Copyright (c) 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_CONTAINTERS_FLAT_SORTED_CONTAINER_BASE_H_
+#define BASE_CONTAINTERS_FLAT_SORTED_CONTAINER_BASE_H_
+
+#include <algorithm>
+#include <iterator>
+#include <memory>
+#include <utility>
+
+namespace base {
+namespace internal {
+
+template <typename Compare>
+struct sort_and_unique : private Compare {
+ template <typename Cont>
+ void operator()(Cont* rhs) {
+ using value_type = typename Cont::value_type;
+
+ std::sort(rhs->begin(), rhs->end(),
+ [this](const value_type& lhs, const value_type& rhs) {
+ return Compare::operator()(lhs, rhs);
+ });
+
+ rhs->erase(
+ std::unique(rhs->begin(), rhs->end(),
+ [this](const value_type& lhs, const value_type& rhs) {
+ return Compare::equal(lhs, rhs);
+ }),
+ rhs->end());
+ }
+};
+
+// Our version of standard library on linux does not have erase with const
+// iterators. It's a hack around that.
+template <typename Cont>
+typename Cont::iterator non_const_iter(Cont* cont,
+ typename Cont::const_iterator iter) {
+ return std::next(cont->begin(), std::distance(cont->cbegin(), iter));
+}
+
+template <typename Compare, class UnderlyingType>
+class flat_sorted_container_base {
+ public:
+ using compare = Compare;
+ using key_compare = compare;
+ using value_compare = compare;
+ using key_value_compare = compare;
+
+ using underlying_type = UnderlyingType;
+ using key_type = typename key_compare::key_type;
+ using value_type = typename key_compare::value_type;
+
+ using size_type = typename underlying_type::size_type;
+ using difference_type = typename underlying_type::difference_type;
+ using reference = typename underlying_type::reference;
+ using const_reference = typename underlying_type::const_reference;
+ using pointer = typename underlying_type::pointer;
+ using const_pointer = typename underlying_type::const_pointer;
+ using iterator = typename underlying_type::iterator;
+ using const_iterator = typename underlying_type::const_iterator;
+ using reverse_iterator = typename underlying_type::reverse_iterator;
+ using const_reverse_iterator =
+ typename underlying_type::const_reverse_iterator;
+
+ // scoped object to do operations on body, without keeping order
+ using unsafe_region =
+ std::unique_ptr<underlying_type, sort_and_unique<compare>>;
+
+ flat_sorted_container_base() {}
+
+ explicit flat_sorted_container_base(underlying_type body)
+ : body_(std::move(body)) {
+ unsafe_access();
+ }
+
+ template <typename It>
+ flat_sorted_container_base(It first, It last) : body_(first, last) {
+ unsafe_access();
+ }
+
+ // methods-------------------------------------------------------------------
+
+ // returns scoped object, that gives access to underlying storrage.
+ // at destruction, sorts and does unification.
+ //
+ // if you know, that on exit of the region, storrage is already sorted and
+ // unified - call unsafe_region::release()
+ unsafe_region unsafe_access() { return unsafe_region(&body_); }
+
+ // get_allocator()
+
+ iterator begin() { return body_.begin(); }
+ const_iterator begin() const { return body_.begin(); }
+ const_iterator cbegin() const { return body_.cbegin(); }
+
+ iterator end() { return body_.end(); }
+ const_iterator end() const { return body_.end(); }
+ const_iterator cend() const { return body_.cend(); }
+
+ reverse_iterator rbegin() { return body_.rbegin(); }
+ const_reverse_iterator rbegin() const { return body_.rbegin(); }
+ const_reverse_iterator crbegin() const { return body_.crbegin(); }
+
+ reverse_iterator rend() { return body_.rend(); }
+ const_reverse_iterator rend() const { return body_.rend(); }
+ const_reverse_iterator crend() const { return body_.crend(); }
+
+ bool empty() const { return body_.empty(); }
+ size_type size() const { return body_.size(); }
+ size_type max_size() const { return body_.max_size(); }
+
+ void clear() { body_.clear(); }
+
+ std::pair<iterator, bool> insert(value_type value) {
+ auto pos = lower_bound(key_value_comp().key_from_value(value));
+ if (pos != end() && value_comp().equal(*pos, value))
+ return std::make_pair(pos, false);
+ return std::make_pair(body_.insert(pos, std::move(value)), true);
+ }
+
+ iterator insert(const_iterator hint, value_type value) {
+ if (hint == body_.end() || value_comp()(value, *hint)) {
+ if (hint == body_.begin() || value_comp()(*(hint - 1), value))
+ return body_.insert(non_const_iter(&body_, hint), std::move(value));
+ }
+ return insert(std::move(value)).first;
+ }
+
+ template <class InputIt>
+ void insert(InputIt first, InputIt last) {
+ std::copy(first, last, std::inserter(*this, end()));
+ }
+
+ // void insert( std::initializer_list<value_type> ilist );
+
+ template <class... Args>
+ std::pair<iterator, bool> emplace(Args&&... args) { // NOLINT
+ // todo(dyaroshev) reverse - use emplace for insert
+ return insert(value_type(std::forward<Args>(args)...)); // NOLINT
+ }
+
+ template <class... Args>
+ iterator emplace_hint(const_iterator hint, Args&&... args) { // NOLINT
+ // todo(dyaroshev) reverse - use emplace for insert
+ return insert(hint, value_type(std::forward<Args>(args)...)); // NOLINT
+ }
+
+ iterator erase(const_iterator position) {
+ return body_.erase(non_const_iter(&body_, position));
+ }
+ void erase(const_iterator first, const_iterator last) {
+ body_.erase(non_const_iter(&body_, first), non_const_iter(&body_, last));
+ }
+
+ size_type erase(const key_type& key) {
+ auto range = equal_range(key);
+ auto res = static_cast<size_type>(std::distance(range.first, range.second));
+ erase(range.first, range.second);
+ return res;
+ }
+
+ void swap(flat_sorted_container_base& other) { body_.swap(other.body_); }
+
+ size_type count(const key_type& key) const {
+ auto range = equal_range(key);
+ return static_cast<size_type>(std::distance(range.first, range.second));
+ }
+
+ iterator find(const key_type& key) {
+ auto pos = lower_bound(key);
+ if (pos == end() || !key_value_comp().equal(*pos, key))
+ return end();
+ return pos;
+ }
+ const_iterator find(const key_type& key) const {
+ auto pos = lower_bound(key);
+ if (pos == end() || !key_value_comp().equal(*pos, key))
+ return end();
+ return pos;
+ }
+
+ std::pair<iterator, iterator> equal_range(const key_type& key) {
+ return std::equal_range(body_.begin(), body_.end(), key, key_value_comp());
+ }
+
+ std::pair<const_iterator, const_iterator> equal_range(
+ const key_type& key) const {
+ return std::equal_range(body_.begin(), body_.end(), key, key_value_comp());
+ }
+
+ iterator lower_bound(const key_type& key) {
+ return std::lower_bound(body_.begin(), body_.end(), key, key_value_comp());
+ }
+
+ const_iterator lower_bound(const key_type& key) const {
+ return std::lower_bound(body_.begin(), body_.end(), key, key_value_comp());
+ }
+
+ iterator upper_bound(const key_type& key) {
+ return std::upper_bound(body_.begin(), body_.end(), key, key_value_comp());
+ }
+
+ const_iterator upper_bound(const key_type& key) const {
+ return std::upper_bound(body_.begin(), body_.end(), key, key_value_comp());
+ }
+
+ key_compare key_comp() const { return key_compare(); }
+
+ value_compare value_comp() const { return value_compare(); }
+
+ key_value_compare key_value_comp() const { return key_value_compare(); }
+
+ // regular-------------------------------------------------------------------
+ // std::map defines it's comparators based on full value compares,
+ // not provided cmps, so equvalent maps are not removed from sets, for example
+
+ friend void swap(flat_sorted_container_base& lhs,
+ flat_sorted_container_base& rhs) {
+ lhs.swap(rhs);
+ }
+
+ friend bool operator==(const flat_sorted_container_base& lhs,
+ const flat_sorted_container_base& rhs) {
+ return lhs.body_ == rhs.body_;
+ }
+
+ friend bool operator!=(const flat_sorted_container_base& lhs,
+ const flat_sorted_container_base& rhs) {
+ return !operator==(lhs, rhs);
+ }
+
+ // totally-ordered-----------------------------------------------------------
+
+ friend bool operator<(const flat_sorted_container_base& lhs,
+ const flat_sorted_container_base& rhs) {
+ return lhs.body_ < rhs.body_;
+ }
+
+ friend bool operator<=(const flat_sorted_container_base& lhs,
+ const flat_sorted_container_base& rhs) {
+ return !(rhs < lhs);
+ }
+
+ friend bool operator>(const flat_sorted_container_base& lhs,
+ const flat_sorted_container_base& rhs) {
+ return rhs < lhs;
+ }
+
+ friend bool operator>=(const flat_sorted_container_base& lhs,
+ const flat_sorted_container_base& rhs) {
+ return !(lhs < rhs);
+ }
+
+ private:
+ underlying_type body_;
+};
+
+} // namespace internal
+
+} // namespace base
+
+#endif // BASE_CONTAINTERS_FLAT_SORTED_CONTAINER_BASE_H_

Powered by Google App Engine
This is Rietveld 408576698