OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 // --- |
| 6 // Author: Simon Que |
| 7 |
| 8 #ifndef _RANKED_LIST_H_ |
| 9 #define _RANKED_LIST_H_ |
| 10 |
| 11 #include <vector> |
| 12 |
| 13 #include "base/basictypes.h" |
| 14 #include "base/custom_allocator.h" |
| 15 #include "base/stl_allocator.h" |
| 16 |
| 17 // RankedList lets you add entries and automatically sorts them internally, so |
| 18 // they can be accessed in sorted order. The entries are stored as a vector |
| 19 // array. |
| 20 |
| 21 namespace leak_detector { |
| 22 |
| 23 template <typename T> |
| 24 class RankedList { |
| 25 public: |
| 26 // A single entry in the RankedList. The RankedList sorts entries by |count|. |
| 27 struct Entry { |
| 28 int count; |
| 29 T value; |
| 30 }; |
| 31 |
| 32 RankedList(size_t max_size) : max_size_(max_size) { |
| 33 entries_.reserve(max_size + 1); |
| 34 } |
| 35 ~RankedList() {} |
| 36 |
| 37 // Access individual element. Does not do boundary checking. |
| 38 const Entry& entry(int index) const { |
| 39 return entries_[index]; |
| 40 } |
| 41 size_t size() const { |
| 42 return entries_.size(); |
| 43 } |
| 44 |
| 45 // Add a new value-count pair to the list. Does not check for existing entries |
| 46 // with the same value. |
| 47 void Add(const T& value, int count); |
| 48 |
| 49 private: |
| 50 // Returns the position to insert a new value. Returns -1 if it cannot be |
| 51 // inserted. |
| 52 int GetInsertionIndex(int count) const; |
| 53 |
| 54 // Max and min counts. |
| 55 const int max_count() const { |
| 56 return entries_.empty() ? 0 : entries_[0].count; |
| 57 } |
| 58 const int min_count() const { |
| 59 return entries_.empty() ? 0 : entries_[size() - 1].count; |
| 60 } |
| 61 |
| 62 // Max number of items in the list. |
| 63 size_t max_size_; |
| 64 |
| 65 // Points to the array of entries. |
| 66 std::vector<Entry, STL_Allocator<Entry, CustomAllocator>> entries_; |
| 67 }; |
| 68 |
| 69 template <typename T> |
| 70 void RankedList<T>::Add(const T& value, int count) { |
| 71 // Determine where to insert the value. |
| 72 int index = GetInsertionIndex(count); |
| 73 if (index == -1) |
| 74 return; |
| 75 |
| 76 entries_.emplace(entries_.begin() + index, Entry({count, value})); |
| 77 |
| 78 // Limit the list size if it exceeds the maximum allowed size. |
| 79 if (entries_.size() > max_size_) |
| 80 entries_.resize(max_size_); |
| 81 } |
| 82 |
| 83 template <typename T> |
| 84 int RankedList<T>::GetInsertionIndex(int count) const { |
| 85 // If the list is full, do not add any entry with |count| if does not exceed |
| 86 // the lowest count of the entries in the list. |
| 87 if (size() == max_size_ && count <= min_count()) |
| 88 return -1; |
| 89 // If larger than the current largest item, insert it before. |
| 90 if (count >= max_count()) |
| 91 return 0; |
| 92 // If smaller than the current smallest item, but the list is not full, |
| 93 // insert it after. |
| 94 if (count <= min_count()) |
| 95 return size(); |
| 96 |
| 97 // Otherwise it's somewhere in the middle, so look for it there. |
| 98 int min_pos = 0; |
| 99 int max_pos = size() - 1; |
| 100 while (max_pos >= min_pos) { |
| 101 int midpoint = (max_pos + min_pos) / 2; |
| 102 if (count >= entries_[midpoint].count && |
| 103 count <= entries_[midpoint - 1].count) { |
| 104 return midpoint; |
| 105 } |
| 106 // The list is reverse sorted. |
| 107 if (entries_[midpoint].count >= count) |
| 108 min_pos = midpoint + 1; |
| 109 else |
| 110 max_pos = midpoint - 1; |
| 111 } |
| 112 return max_pos; |
| 113 } |
| 114 |
| 115 } // namespace leak_detector |
| 116 |
| 117 #endif // _RANKED_LIST_H_ |
OLD | NEW |