Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / tools / gn / unique_vector.h
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 lass allows us to insert things by reference into a hash table which
15 // avoids copies. The hash function of a UniquifyRef is that of the object it
16 // points to.
17 //
18 // There are two ways it can store data: (1) by (vector*, index) which is used
19 // to refer to the array in UniqueVector and make it work even when the
20 // underlying vector is reallocated; (2) by T* which is used to do lookups
21 // into the hash table of things that aren't in a vector yet.
22 //
23 // It also caches the hash value which allows us to query and then insert
24 // without recomputing the hash.
25 template<typename T>
26 class UniquifyRef {
27  public:
28   UniquifyRef()
29       : value_(NULL),
30         vect_(NULL),
31         index_(static_cast<size_t>(-1)),
32         hash_val_(0) {
33   }
34
35   // Initialize with a pointer to a value.
36   UniquifyRef(const T* v)
37       : value_(v),
38         vect_(NULL),
39         index_(static_cast<size_t>(-1)) {
40     FillHashValue();
41   }
42
43   // Initialize with an array + index.
44   UniquifyRef(const std::vector<T>* v, size_t i)
45       : value_(NULL),
46         vect_(v),
47         index_(i) {
48     FillHashValue();
49   }
50
51   // Initialize with an array + index and a known hash value to prevent
52   // re-hashing.
53   UniquifyRef(const std::vector<T>* v, size_t i, size_t hash_value)
54       : value_(NULL),
55         vect_(v),
56         index_(i),
57         hash_val_(hash_value) {
58   }
59
60   const T& value() const { return value_ ? *value_ : (*vect_)[index_]; }
61   size_t hash_val() const { return hash_val_; }
62   size_t index() const { return index_; }
63
64  private:
65   void FillHashValue() {
66     BASE_HASH_NAMESPACE::hash<T> h;
67     hash_val_ = h(value());
68   }
69
70   // When non-null, points to the object.
71   const T* value_;
72
73   // When value is null these are used.
74   const std::vector<T>* vect_;
75   size_t index_;
76
77   size_t hash_val_;
78 };
79
80 template<typename T> inline bool operator==(const UniquifyRef<T>& a,
81                                             const UniquifyRef<T>& b) {
82   return a.value() == b.value();
83 }
84
85 template<typename T> inline bool operator<(const UniquifyRef<T>& a,
86                                            const UniquifyRef<T>& b) {
87   return a.value() < b.value();
88 }
89
90 }  // namespace internal
91
92 namespace BASE_HASH_NAMESPACE {
93
94 template<typename T> struct hash< internal::UniquifyRef<T> > {
95   std::size_t operator()(const internal::UniquifyRef<T>& v) const {
96     return v.hash_val();
97   }
98 };
99
100 }  // namespace BASE_HASH_NAMESPACE
101
102 // An ordered set optimized for GN's usage. Such sets are used to store lists
103 // of configs and libraries, and are appended to but not randomly inserted
104 // into.
105 template<typename T>
106 class UniqueVector {
107  public:
108   typedef std::vector<T> Vector;
109   typedef typename Vector::iterator iterator;
110   typedef typename Vector::const_iterator const_iterator;
111
112   const Vector& vector() const { return vector_; }
113   size_t size() const { return vector_.size(); }
114   bool empty() const { return vector_.empty(); }
115   void clear() { vector_.clear(); set_.clear(); }
116   void reserve(size_t s) { vector_.reserve(s); }
117
118   const T& operator[](size_t index) const { return vector_[index]; }
119
120   const_iterator begin() const { return vector_.begin(); }
121   iterator begin() { return vector_.begin(); }
122   const_iterator end() const { return vector_.end(); }
123   iterator end() { return vector_.end(); }
124
125   // Returns true if the item was appended, false if it already existed (and
126   // thus the vector was not modified).
127   bool push_back(const T& t) {
128     Ref ref(&t);
129     if (set_.find(ref) != set_.end())
130       return false;  // Already have this one.
131
132     vector_.push_back(t);
133     set_.insert(Ref(&vector_, vector_.size() - 1, ref.hash_val()));
134     return true;
135   }
136
137   // Like push_back but swaps in the type to avoid a copy.
138   bool PushBackViaSwap(T* t) {
139     using std::swap;
140
141     Ref ref(t);
142     if (set_.find(ref) != set_.end())
143       return false;  // Already have this one.
144
145     size_t new_index = vector_.size();
146     vector_.resize(new_index + 1);
147     swap(vector_[new_index], *t);
148     set_.insert(Ref(&vector_, vector_.size() - 1, ref.hash_val()));
149     return true;
150   }
151
152   // Appends a range of items from an iterator.
153   template<typename iter> void Append(const iter& begin, const iter& end) {
154     for (iter i = begin; i != end; ++i)
155       push_back(*i);
156   }
157
158   // Returns the index of the item matching the given value in the list, or
159   // (size_t)(-1) if it's not found.
160   size_t IndexOf(const T& t) const {
161     Ref ref(&t);
162     typename HashSet::const_iterator found = set_.find(ref);
163     if (found == set_.end())
164       return static_cast<size_t>(-1);
165     return found->index();
166   }
167
168  private:
169   typedef internal::UniquifyRef<T> Ref;
170   typedef base::hash_set<Ref> HashSet;
171
172   HashSet set_;
173   Vector vector_;
174 };
175
176 #endif  // TOOLS_GN_UNIQUE_VECTOR_H_