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

Side by Side Diff: chrome/browser/sync/util/enum_set.h

Issue 8772073: [Sync] Add new EnumSet class representing a set of enum values (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Addressed comments Created 9 years 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | chrome/browser/sync/util/enum_set_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 (c) 2011 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 CHROME_BROWSER_SYNC_UTIL_ENUM_SET_H_
6 #define CHROME_BROWSER_SYNC_UTIL_ENUM_SET_H_
7 #pragma once
8
9 #include <bitset>
10 #include <cstddef>
11 #include <string>
12
13 #include "base/basictypes.h"
14 #include "base/logging.h"
15
16 namespace browser_sync {
17
18 // Forward declarations needed for friend declarations.
19 template <typename E, E MinEnumValue, E MaxEnumValue>
20 class EnumSet;
21
22 template <typename E, E Min, E Max>
23 EnumSet<E, Min, Max> Union(EnumSet<E, Min, Max> set1,
24 EnumSet<E, Min, Max> set2);
25
26 template <typename E, E Min, E Max>
27 EnumSet<E, Min, Max> Intersection(EnumSet<E, Min, Max> set1,
28 EnumSet<E, Min, Max> set2);
29
30 template <typename E, E Min, E Max>
31 EnumSet<E, Min, Max> Difference(EnumSet<E, Min, Max> set1,
32 EnumSet<E, Min, Max> set2);
33
34 // An EnumSet is a set that can hold enum values between a min and a
35 // max value (inclusive of both). It's essentially a wrapper around
36 // std::bitset<> with stronger type enforcement, more descriptive
37 // member function names, and an iterator interface.
38 //
39 // If you're working with enums with a small number of possible values
40 // (say, fewer than 64), you can efficiently pass around an EnumSet
41 // for that enum around by value.
42
43 template <typename E, E MinEnumValue, E MaxEnumValue>
44 class EnumSet {
45 public:
46 typedef E EnumType;
47 static const E kMinValue = MinEnumValue;
48 static const E kMaxValue = MaxEnumValue;
49 static const size_t kValueCount = kMaxValue - kMinValue + 1;
50 COMPILE_ASSERT(kMinValue < kMaxValue,
51 min_value_must_be_less_than_max_value);
52
53 private:
54 // Declaration needed by Iterator.
55 typedef std::bitset<kValueCount> EnumBitSet;
56
57 public:
58 // Iterator is a forward-only read-only iterator for EnumSet. Its
59 // interface is deliberately distinct from an STL iterator as its
60 // semantics are substantially different.
61 //
62 // Example usage:
63 //
64 // for (EnumSet<...>::Iterator it = enums.First(); it.Good(); it.Inc()) {
65 // Process(it.Get());
66 // }
67 //
68 // There are no guarantees as to what will happen if you modify an
69 // EnumSet while traversing it with an iterator.
70 class Iterator {
71 public:
72 // A default-constructed iterator can't do anything except check
73 // Good(). You need to call First() on an EnumSet to get a usable
74 // iterator.
75 Iterator() : enums_(NULL), i_(kValueCount) {}
76 ~Iterator() {}
77
78 // Copy constructor and assignment welcome.
79
80 // Returns true iff the iterator points to an EnumSet and it
81 // hasn't yet traversed the EnumSet entirely.
82 bool Good() const {
83 return enums_ && i_ < kValueCount && enums_->test(i_);
84 }
85
86 // Returns the value the iterator currently points to. Good()
87 // must hold.
88 E Get() const {
89 CHECK(Good());
90 return FromIndex(i_);
91 }
92
93 // Moves the iterator to the next value in the EnumSet. Good()
94 // must hold. Takes linear time.
95 void Inc() {
96 CHECK(Good());
97 i_ = FindNext(i_ + 1);
98 }
99
100 private:
101 friend Iterator EnumSet::First() const;
102
103 explicit Iterator(const EnumBitSet& enums)
104 : enums_(&enums), i_(FindNext(0)) {}
105
106 size_t FindNext(size_t i) {
107 while ((i < kValueCount) && !enums_->test(i)) {
108 ++i;
109 }
110 return i;
111 }
112
113 const EnumBitSet* enums_;
114 size_t i_;
115 };
116
117 // You can construct an EnumSet with 0, 1, 2, or 3 initial values.
118
119 EnumSet() {}
120
121 explicit EnumSet(E value) {
122 Put(value);
123 }
124
125 EnumSet(E value1, E value2) {
126 Put(value1);
127 Put(value2);
128 }
129
130 EnumSet(E value1, E value2, E value3) {
131 Put(value1);
132 Put(value2);
133 Put(value3);
134 }
135
136 // Returns an EnumSet with all possible values.
137 static EnumSet All() {
138 EnumBitSet enums;
139 enums.set();
140 return EnumSet(enums);
141 }
142
143 ~EnumSet() {}
144
145 // Copy constructor and assignment welcome.
146
147 // Set operations. Put, Retain, and Remove are basically
148 // self-mutating versions of Union, Intersection, and Difference
149 // (defined below).
150
151 // Adds the given value to our set.
152 void Put(E value) {
153 enums_.set(ToIndex(value));
154 }
155
156 // Adds all values in the given set to our set.
157 void PutAll(EnumSet other) {
158 enums_ |= other.enums_;
159 }
160
161 // There's no real need for a Retain(E) member function.
162
163 // Removes all values not in the given set from our set.
164 void RetainAll(EnumSet other) {
165 enums_ &= other.enums_;
166 }
167
168 // Removes the given value from our set.
169 void Remove(E value) {
170 enums_.reset(ToIndex(value));
171 }
172
173 // Removes all values in the given set from our set.
174 void RemoveAll(EnumSet other) {
175 enums_ &= ~other.enums_;
176 }
177
178 // Removes all values from our set.
179 void Clear() {
180 enums_.reset();
181 }
182
183 // Returns true iff the given value is a member of our set.
184 bool Has(E value) const {
185 return enums_.test(ToIndex(value));
186 }
187
188 // Returns true iff the given set is a subset of our set.
189 bool HasAll(EnumSet other) const {
190 return (enums_ & other.enums_) == other.enums_;
191 }
192
193 // Returns true iff our set and the given set contain exactly the
194 // same values.
195 bool Equals(const EnumSet& other) const {
196 return enums_ == other.enums_;
197 }
198
199 // Returns true iff our set is empty.
200 bool Empty() const {
201 return !enums_.any();
202 }
203
204 // Returns how many values our set has.
205 size_t Size() const {
206 return enums_.count();
207 }
208
209 // Returns an iterator pointing to the first element (if any).
210 Iterator First() const {
211 return Iterator(enums_);
212 }
213
214 private:
215 friend EnumSet Union<E, MinEnumValue, MaxEnumValue>(
216 EnumSet set1, EnumSet set2);
217 friend EnumSet Intersection<E, MinEnumValue, MaxEnumValue>(
218 EnumSet set1, EnumSet set2);
219 friend EnumSet Difference<E, MinEnumValue, MaxEnumValue>(
220 EnumSet set1, EnumSet set2);
221
222 explicit EnumSet(EnumBitSet enums) : enums_(enums) {}
223
224 // Converts a value to/from an index into |enums_|.
225
226 static size_t ToIndex(E value) {
227 DCHECK_GE(value, MinEnumValue);
228 DCHECK_LE(value, MaxEnumValue);
229 return value - MinEnumValue;
230 }
231
232 static E FromIndex(size_t i) {
233 DCHECK_LT(i, kValueCount);
234 return static_cast<E>(MinEnumValue + i);
235 }
236
237 EnumBitSet enums_;
238 };
239
240 template <typename E, E MinEnumValue, E MaxEnumValue>
241 const E EnumSet<E, MinEnumValue, MaxEnumValue>::kMinValue;
242
243 template <typename E, E MinEnumValue, E MaxEnumValue>
244 const E EnumSet<E, MinEnumValue, MaxEnumValue>::kMaxValue;
245
246 template <typename E, E MinEnumValue, E MaxEnumValue>
247 const size_t EnumSet<E, MinEnumValue, MaxEnumValue>::kValueCount;
248
249 // The usual set operations.
250
251 template <typename E, E Min, E Max>
252 EnumSet<E, Min, Max> Union(EnumSet<E, Min, Max> set1,
253 EnumSet<E, Min, Max> set2) {
254 return EnumSet<E, Min, Max>(set1.enums_ | set2.enums_);
255 }
256
257 template <typename E, E Min, E Max>
258 EnumSet<E, Min, Max> Intersection(EnumSet<E, Min, Max> set1,
259 EnumSet<E, Min, Max> set2) {
260 return EnumSet<E, Min, Max>(set1.enums_ & set2.enums_);
261 }
262
263 template <typename E, E Min, E Max>
264 EnumSet<E, Min, Max> Difference(EnumSet<E, Min, Max> set1,
265 EnumSet<E, Min, Max> set2) {
266 return EnumSet<E, Min, Max>(set1.enums_ & ~set2.enums_);
267 }
268
269 } // namespace browser_sync
270
271 #endif // CHROME_BROWSER_SYNC_UTIL_ENUM_SET_H_
OLDNEW
« no previous file with comments | « no previous file | chrome/browser/sync/util/enum_set_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698