OLD | NEW |
---|---|
1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef BASE_CONTAINERS_FLAT_TREE_H_ | 5 #ifndef BASE_CONTAINERS_FLAT_TREE_H_ |
6 #define BASE_CONTAINERS_FLAT_TREE_H_ | 6 #define BASE_CONTAINERS_FLAT_TREE_H_ |
7 | 7 |
8 #include <algorithm> | 8 #include <algorithm> |
9 #include <iterator> | |
9 #include <vector> | 10 #include <vector> |
10 | 11 |
11 namespace base { | 12 namespace base { |
12 | 13 |
13 enum FlatContainerDupes { | 14 enum FlatContainerDupes { |
14 KEEP_FIRST_OF_DUPES, | 15 KEEP_FIRST_OF_DUPES, |
15 KEEP_LAST_OF_DUPES, | 16 KEEP_LAST_OF_DUPES, |
16 }; | 17 }; |
17 | 18 |
18 namespace internal { | 19 namespace internal { |
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
180 const_reverse_iterator crbegin() const; | 181 const_reverse_iterator crbegin() const; |
181 | 182 |
182 reverse_iterator rend(); | 183 reverse_iterator rend(); |
183 const_reverse_iterator rend() const; | 184 const_reverse_iterator rend() const; |
184 const_reverse_iterator crend() const; | 185 const_reverse_iterator crend() const; |
185 | 186 |
186 // -------------------------------------------------------------------------- | 187 // -------------------------------------------------------------------------- |
187 // Insert operations. | 188 // Insert operations. |
188 // | 189 // |
189 // Assume that every operation invalidates iterators and references. | 190 // Assume that every operation invalidates iterators and references. |
190 // Insertion of one element can take O(size). See the Notes section in the | 191 // Insertion of one element can take O(size). Capacity of flat_tree grows in |
191 // class comments on why we do not currently implement range insertion. | 192 // an implementation-defined manner. |
192 // Capacity of flat_tree grows in an implementation-defined manner. | |
193 // | 193 // |
194 // NOTE: Prefer to build a new flat_tree from a std::vector (or similar) | 194 // NOTE: Prefer to build a new flat_tree from a std::vector (or similar) |
195 // instead of calling insert() repeatedly. | 195 // instead of calling insert() repeatedly. |
196 | 196 |
197 std::pair<iterator, bool> insert(const value_type& val); | 197 std::pair<iterator, bool> insert(const value_type& val); |
198 std::pair<iterator, bool> insert(value_type&& val); | 198 std::pair<iterator, bool> insert(value_type&& val); |
199 | 199 |
200 iterator insert(const_iterator position_hint, const value_type& x); | 200 iterator insert(const_iterator position_hint, const value_type& x); |
201 iterator insert(const_iterator position_hint, value_type&& x); | 201 iterator insert(const_iterator position_hint, value_type&& x); |
202 | 202 |
203 template <class InputIterator> | |
204 void insert(InputIterator first, | |
brettw
2017/05/10 16:52:06
Can you add a comment here about FlatContainerDupe
jdoerrie
2017/05/11 06:34:57
Done.
| |
205 InputIterator last, | |
206 FlatContainerDupes dupes); | |
207 | |
203 template <class... Args> | 208 template <class... Args> |
204 std::pair<iterator, bool> emplace(Args&&... args); | 209 std::pair<iterator, bool> emplace(Args&&... args); |
205 | 210 |
206 template <class... Args> | 211 template <class... Args> |
207 iterator emplace_hint(const_iterator position_hint, Args&&... args); | 212 iterator emplace_hint(const_iterator position_hint, Args&&... args); |
208 | 213 |
209 // -------------------------------------------------------------------------- | 214 // -------------------------------------------------------------------------- |
210 // Erase operations. | 215 // Erase operations. |
211 // | 216 // |
212 // Assume that every operation invalidates iterators and references. | 217 // Assume that every operation invalidates iterators and references. |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
309 const key_compare& key_comp_; | 314 const key_compare& key_comp_; |
310 }; | 315 }; |
311 | 316 |
312 const flat_tree& as_const() { return *this; } | 317 const flat_tree& as_const() { return *this; } |
313 | 318 |
314 iterator const_cast_it(const_iterator c_it) { | 319 iterator const_cast_it(const_iterator c_it) { |
315 auto distance = std::distance(cbegin(), c_it); | 320 auto distance = std::distance(cbegin(), c_it); |
316 return std::next(begin(), distance); | 321 return std::next(begin(), distance); |
317 } | 322 } |
318 | 323 |
319 void sort_and_unique(FlatContainerDupes dupes) { | 324 void sort_and_unique(iterator first, |
325 iterator last, | |
326 FlatContainerDupes dupes) { | |
320 // Preserve stability for the unique code below. | 327 // Preserve stability for the unique code below. |
321 std::stable_sort(begin(), end(), impl_.get_value_comp()); | 328 std::stable_sort(first, last, impl_.get_value_comp()); |
322 | 329 |
323 auto comparator = [this](const value_type& lhs, const value_type& rhs) { | 330 auto comparator = [this](const value_type& lhs, const value_type& rhs) { |
324 // lhs is already <= rhs due to sort, therefore | 331 // lhs is already <= rhs due to sort, therefore |
325 // !(lhs < rhs) <=> lhs == rhs. | 332 // !(lhs < rhs) <=> lhs == rhs. |
326 return !impl_.get_value_comp()(lhs, rhs); | 333 return !impl_.get_value_comp()(lhs, rhs); |
327 }; | 334 }; |
328 | 335 |
329 iterator erase_after; | 336 iterator erase_after; |
330 switch (dupes) { | 337 switch (dupes) { |
331 case KEEP_FIRST_OF_DUPES: | 338 case KEEP_FIRST_OF_DUPES: |
332 erase_after = std::unique(begin(), end(), comparator); | 339 erase_after = std::unique(first, last, comparator); |
333 break; | 340 break; |
334 case KEEP_LAST_OF_DUPES: | 341 case KEEP_LAST_OF_DUPES: |
335 erase_after = LastUnique(begin(), end(), comparator); | 342 erase_after = LastUnique(first, last, comparator); |
336 break; | 343 break; |
337 } | 344 } |
338 erase(erase_after, end()); | 345 erase(erase_after, last); |
339 } | 346 } |
340 | 347 |
341 // To support comparators that may not be possible to default-construct, we | 348 // To support comparators that may not be possible to default-construct, we |
342 // have to store an instance of Compare. Using this to store all internal | 349 // have to store an instance of Compare. Using this to store all internal |
343 // state of flat_tree and using private inheritance to store compare lets us | 350 // state of flat_tree and using private inheritance to store compare lets us |
344 // take advantage of an empty base class optimization to avoid extra space in | 351 // take advantage of an empty base class optimization to avoid extra space in |
345 // the common case when Compare has no state. | 352 // the common case when Compare has no state. |
346 struct Impl : private value_compare { | 353 struct Impl : private value_compare { |
347 Impl() = default; | 354 Impl() = default; |
348 | 355 |
(...skipping 21 matching lines...) Expand all Loading... | |
370 : impl_(comp) {} | 377 : impl_(comp) {} |
371 | 378 |
372 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> | 379 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> |
373 template <class InputIterator> | 380 template <class InputIterator> |
374 flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::flat_tree( | 381 flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::flat_tree( |
375 InputIterator first, | 382 InputIterator first, |
376 InputIterator last, | 383 InputIterator last, |
377 FlatContainerDupes dupe_handling, | 384 FlatContainerDupes dupe_handling, |
378 const KeyCompare& comp) | 385 const KeyCompare& comp) |
379 : impl_(comp, first, last) { | 386 : impl_(comp, first, last) { |
380 sort_and_unique(dupe_handling); | 387 sort_and_unique(begin(), end(), dupe_handling); |
381 } | 388 } |
382 | 389 |
383 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> | 390 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> |
384 flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::flat_tree( | 391 flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::flat_tree( |
385 const flat_tree&) = default; | 392 const flat_tree&) = default; |
386 | 393 |
387 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> | 394 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> |
388 flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::flat_tree(flat_tree&&) = | 395 flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::flat_tree(flat_tree&&) = |
389 default; | 396 default; |
390 | 397 |
391 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> | 398 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> |
392 flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::flat_tree( | 399 flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::flat_tree( |
393 std::vector<value_type> items, | 400 std::vector<value_type> items, |
394 FlatContainerDupes dupe_handling, | 401 FlatContainerDupes dupe_handling, |
395 const KeyCompare& comp) | 402 const KeyCompare& comp) |
396 : impl_(comp, std::move(items)) { | 403 : impl_(comp, std::move(items)) { |
397 sort_and_unique(dupe_handling); | 404 sort_and_unique(begin(), end(), dupe_handling); |
398 } | 405 } |
399 | 406 |
400 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> | 407 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> |
401 flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::flat_tree( | 408 flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::flat_tree( |
402 std::initializer_list<value_type> ilist, | 409 std::initializer_list<value_type> ilist, |
403 FlatContainerDupes dupe_handling, | 410 FlatContainerDupes dupe_handling, |
404 const KeyCompare& comp) | 411 const KeyCompare& comp) |
405 : flat_tree(std::begin(ilist), std::end(ilist), dupe_handling, comp) {} | 412 : flat_tree(std::begin(ilist), std::end(ilist), dupe_handling, comp) {} |
406 | 413 |
407 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> | 414 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> |
408 flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::~flat_tree() = default; | 415 flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::~flat_tree() = default; |
409 | 416 |
410 // ---------------------------------------------------------------------------- | 417 // ---------------------------------------------------------------------------- |
411 // Assignments. | 418 // Assignments. |
412 | 419 |
413 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> | 420 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> |
414 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::operator=( | 421 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::operator=( |
415 const flat_tree&) -> flat_tree& = default; | 422 const flat_tree&) -> flat_tree& = default; |
416 | 423 |
417 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> | 424 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> |
418 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::operator=(flat_tree &&) | 425 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::operator=(flat_tree &&) |
419 -> flat_tree& = default; | 426 -> flat_tree& = default; |
420 | 427 |
421 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> | 428 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> |
422 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::operator=( | 429 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::operator=( |
423 std::initializer_list<value_type> ilist) -> flat_tree& { | 430 std::initializer_list<value_type> ilist) -> flat_tree& { |
424 impl_.body_ = ilist; | 431 impl_.body_ = ilist; |
425 sort_and_unique(KEEP_FIRST_OF_DUPES); | 432 sort_and_unique(begin(), end(), KEEP_FIRST_OF_DUPES); |
426 return *this; | 433 return *this; |
427 } | 434 } |
428 | 435 |
429 // ---------------------------------------------------------------------------- | 436 // ---------------------------------------------------------------------------- |
430 // Memory management. | 437 // Memory management. |
431 | 438 |
432 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> | 439 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> |
433 void flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::reserve( | 440 void flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::reserve( |
434 size_type new_capacity) { | 441 size_type new_capacity) { |
435 impl_.body_.reserve(new_capacity); | 442 impl_.body_.reserve(new_capacity); |
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
596 if (position_hint == end() || impl_.get_value_comp()(val, *position_hint)) { | 603 if (position_hint == end() || impl_.get_value_comp()(val, *position_hint)) { |
597 if (position_hint == begin() || | 604 if (position_hint == begin() || |
598 impl_.get_value_comp()(*(position_hint - 1), val)) | 605 impl_.get_value_comp()(*(position_hint - 1), val)) |
599 // We have to cast away const because of crbug.com/677044. | 606 // We have to cast away const because of crbug.com/677044. |
600 return impl_.body_.insert(const_cast_it(position_hint), std::move(val)); | 607 return impl_.body_.insert(const_cast_it(position_hint), std::move(val)); |
601 } | 608 } |
602 return insert(std::move(val)).first; | 609 return insert(std::move(val)).first; |
603 } | 610 } |
604 | 611 |
605 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> | 612 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> |
613 template <class InputIterator> | |
614 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::insert( | |
615 InputIterator first, | |
616 InputIterator last, | |
617 FlatContainerDupes dupes) -> void { | |
618 // Initialize the first insertion point and provide a convenience lambda to | |
619 // obtain an iterator pointing past the old element. This needs to be dymanic | |
620 // due to possible re-allocations. | |
621 difference_type pos_first_new = std::distance(begin(), end()); | |
dyaroshev
2017/05/10 17:12:09
Nit:
Just say size()? Or are there problems with d
jdoerrie
2017/05/11 06:34:57
Done both now. There usually is a difference, diff
| |
622 auto middle = [this, pos_first_new]() { | |
623 return std::next(begin(), pos_first_new); | |
624 }; | |
dyaroshev
2017/05/10 17:12:09
How do you feel about reserve if we can compute di
jdoerrie
2017/05/11 06:34:57
I don't like using reserve, because it can lead to
dyaroshev
2017/05/11 09:46:43
That's a good point.
| |
625 | |
626 for (; first != last; ++first) { | |
627 iterator lower = std::lower_bound(begin(), middle(), *first, value_comp()); | |
628 if (lower == middle() || value_comp()(*first, *lower)) { | |
629 // Insert completely new elements at the back. | |
630 pos_first_new = std::min(pos_first_new, std::distance(begin(), lower)); | |
631 impl_.body_.push_back(*first); | |
632 } else if (lower != middle() && dupes == KEEP_LAST_OF_DUPES) { | |
dyaroshev
2017/05/10 17:12:09
1 - The check for (dupes == KEEP_LAST_OF_DUPES) sh
jdoerrie
2017/05/11 06:34:57
Done.
| |
633 // Only overwrite existing elements in case of KEEP_LAST_OF_DUPES. | |
634 *lower = *first; | |
635 } | |
636 } | |
637 | |
638 // The new elements might be unordered and contain duplicates, so post-process | |
639 // the just inserted elements and merge them with the rest, inserting them at | |
640 // the previously found spot. | |
641 sort_and_unique(middle(), end(), dupes); | |
642 std::inplace_merge(std::next(begin(), pos_first_new), middle(), end(), | |
643 value_comp()); | |
dyaroshev
2017/05/10 17:12:09
Have you measured? Are you closer now to inserting
jdoerrie
2017/05/11 06:34:57
See above.
| |
644 } | |
645 | |
646 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> | |
606 template <class... Args> | 647 template <class... Args> |
607 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::emplace(Args&&... args) | 648 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::emplace(Args&&... args) |
608 -> std::pair<iterator, bool> { | 649 -> std::pair<iterator, bool> { |
609 return insert(value_type(std::forward<Args>(args)...)); | 650 return insert(value_type(std::forward<Args>(args)...)); |
610 } | 651 } |
611 | 652 |
612 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> | 653 template <class Key, class Value, class GetKeyFromValue, class KeyCompare> |
613 template <class... Args> | 654 template <class... Args> |
614 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::emplace_hint( | 655 auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::emplace_hint( |
615 const_iterator position_hint, | 656 const_iterator position_hint, |
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
768 void EraseIf(base::internal::flat_tree<Key, Value, GetKeyFromValue, KeyCompare>& | 809 void EraseIf(base::internal::flat_tree<Key, Value, GetKeyFromValue, KeyCompare>& |
769 container, | 810 container, |
770 Predicate pred) { | 811 Predicate pred) { |
771 container.erase(std::remove_if(container.begin(), container.end(), pred), | 812 container.erase(std::remove_if(container.begin(), container.end(), pred), |
772 container.end()); | 813 container.end()); |
773 } | 814 } |
774 | 815 |
775 } // namespace base | 816 } // namespace base |
776 | 817 |
777 #endif // BASE_CONTAINERS_FLAT_TREE_H_ | 818 #endif // BASE_CONTAINERS_FLAT_TREE_H_ |
OLD | NEW |