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

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