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

Side by Side Diff: tools/gn/unique_vector.h

Issue 26537002: Add a UniqueVector class to GN (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: clang npos Created 6 years, 4 months 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 unified diff | Download patch
« no previous file with comments | « tools/gn/target_unittest.cc ('k') | tools/gn/unique_vector_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2014 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 #ifndef TOOLS_GN_UNIQUE_VECTOR_H_
6 #define TOOLS_GN_UNIQUE_VECTOR_H_
7
8 #include <algorithm>
9
10 #include "base/containers/hash_tables.h"
11
12 namespace internal {
13
14 // This struct allows us to insert things by reference into a hash table. This
viettrungluu 2014/08/06 19:43:52 Which struct are you talking about? (Actually, th
15 // is used to avoid copying strings just to uniquify them. The hash function
16 // of a UniquifyRef is that of the object it points to.
17 //
18 // It also caches the hash value which allows us to query and then insert
19 // without recomputing the hash.
20 template<typename T>
21 class UniquifyRef {
22 public:
23 UniquifyRef()
24 : value_(NULL),
25 vect_(NULL),
26 index_(static_cast<size_t>(-1)),
27 hash_val_(0) {
28 }
29
30 // Initialize with a pointer to a value.
31 UniquifyRef(const T* v)
32 : value_(v),
33 vect_(NULL),
34 index_(static_cast<size_t>(-1)) {
35 FillHashValue();
36 }
37
38 // Initialize with an array + index.
39 UniquifyRef(const std::vector<T>* v, size_t i)
viettrungluu 2014/08/06 19:43:52 Why would you use this instead of passing &v[i] to
brettw 2014/08/06 20:13:03 I clarified the class-level comment. The vector*+i
40 : value_(NULL),
41 vect_(v),
42 index_(i) {
43 FillHashValue();
44 }
45
46 // Initialize with an array + index and a know hash value to prevent
viettrungluu 2014/08/06 19:43:52 s/know/known/ I assume.
47 // re-hashing.
48 UniquifyRef(const std::vector<T>* v, size_t i, size_t hash_value)
49 : value_(NULL),
50 vect_(v),
51 index_(i),
52 hash_val_(hash_value) {
53 }
54
55 const T& value() const { return value_ ? *value_ : (*vect_)[index_]; }
56 size_t hash_val() const { return hash_val_; }
57 size_t index() const { return index_; }
58
59 private:
60 void FillHashValue() {
61 #if defined(COMPILER_GCC)
62 BASE_HASH_NAMESPACE::hash<T> h;
63 hash_val_ = h(value());
64 #elif defined(COMPILER_MSVC)
65 hash_val_ = BASE_HASH_NAMESPACE::hash_value(value());
66 #else
67 #error write me
68 #endif // COMPILER...
69 }
70
71 // When non-null, points to the object.
72 const T* value_;
73
74 // When value is null these are used.
75 const std::vector<T>* vect_;
76 size_t index_;
77
78 size_t hash_val_;
79 };
80
81 template<typename T> inline bool operator==(const UniquifyRef<T>& a,
82 const UniquifyRef<T>& b) {
83 return a.value() == b.value();
84 }
85
86 template<typename T> inline bool operator<(const UniquifyRef<T>& a,
87 const UniquifyRef<T>& b) {
88 return a.value() < b.value();
89 }
90
91 } // namespace internal
92
93 namespace BASE_HASH_NAMESPACE {
94
95 #if defined(COMPILER_GCC)
96 template<typename T> struct hash< internal::UniquifyRef<T> > {
97 std::size_t operator()(const internal::UniquifyRef<T>& v) const {
98 return v.hash_val();
99 }
100 };
101 #elif defined(COMPILER_MSVC)
102 template<typename T>
103 inline size_t hash_value(const internal::UniquifyRef<T>& v) {
104 return v.hash_val();
105 }
106 #endif // COMPILER...
107
108 } // namespace BASE_HASH_NAMESPACE
109
110 // An ordered set optimized for GN's usage. Such sets are used to store lists
111 // of configs and libraries, and are appended to but not
viettrungluu 2014/08/06 19:43:52 appended to but not ... what?
112 template<typename T>
113 class UniqueVector {
114 public:
115 typedef std::vector<T> Vector;
116 typedef typename Vector::iterator iterator;
117 typedef typename Vector::const_iterator const_iterator;
118 const size_t npos = static_cast<size_t>(-1);
119
120 const Vector& vector() const { return vector_; }
121 size_t size() const { return vector_.size(); }
122 bool empty() const { return vector_.empty(); }
123 void clear() { vector_.clear(); set_.clear(); }
124 void reserve(size_t s) { vector_.reserve(s); }
125
126 const T& operator[](size_t index) const { return vector_[index]; }
127
128 const_iterator begin() const { return vector_.begin(); }
129 iterator begin() { return vector_.begin(); }
130 const_iterator end() const { return vector_.end(); }
131 iterator end() { return vector_.end(); }
132
133 // Returns true if the item was appended, false if it already existed (and
134 // thus the vector was not modified).
135 bool push_back(const T& t) {
136 Ref ref(&t);
137 if (set_.find(ref) != set_.end())
138 return false; // Already have this one.
139
140 vector_.push_back(t);
141 set_.insert(Ref(&vector_, vector_.size() - 1, ref.hash_val()));
142 return true;
143 }
144
145 // Like push_back but swaps in the type to avoid a copy.
146 bool PushBackViaSwap(T* t) {
147 using std::swap;
148
149 Ref ref(t);
150 if (set_.find(ref) != set_.end())
151 return false; // Already have this one.
152
153 size_t new_index = vector_.size();
154 vector_.resize(new_index + 1);
155 swap(vector_[new_index], *t);
156 set_.insert(Ref(&vector_, vector_.size() - 1, ref.hash_val()));
157 return true;
158 }
159
160 // Appends a range of items from an iterator.
161 template<typename iter> void Append(const iter& begin, const iter& end) {
162 for (iter i = begin; i < end; i++)
viettrungluu 2014/08/06 19:43:52 Generally preferred: != end ++i
163 push_back(*i);
viettrungluu 2014/08/06 19:43:52 Maybe you should have a (debug-only) assertion abo
brettw 2014/08/06 20:13:03 This calls push_back which handles duplicate eleme
164 }
165
166 // Returns the index of the item matching the given value in the list, or
167 // npos if it's not found.
168 size_t IndexOf(const T& t) const {
169 Ref ref(&t);
170 typename HashSet::const_iterator found = set_.find(ref);
171 if (found == set_.end())
172 return npos;
173 return found->index();
174 }
175
176 private:
177 typedef internal::UniquifyRef<T> Ref;
178 typedef base::hash_set<Ref> HashSet;
179
180 HashSet set_;
181 Vector vector_;
182 };
183
184 #endif // TOOLS_GN_UNIQUE_VECTOR_H_
OLDNEW
« no previous file with comments | « tools/gn/target_unittest.cc ('k') | tools/gn/unique_vector_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698