OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef SYNC_INTERNAL_API_PUBLIC_BASE_ENUM_SET_H_ | 5 #ifndef COMPONENTS_SYNC_BASE_ENUM_SET_H_ |
6 #define SYNC_INTERNAL_API_PUBLIC_BASE_ENUM_SET_H_ | 6 #define COMPONENTS_SYNC_BASE_ENUM_SET_H_ |
7 | 7 |
8 #include <bitset> | 8 #include <bitset> |
9 #include <cstddef> | 9 #include <cstddef> |
10 #include <string> | 10 #include <string> |
11 | 11 |
12 #include "base/logging.h" | 12 #include "base/logging.h" |
13 | 13 |
14 namespace syncer { | 14 namespace syncer { |
15 | 15 |
16 // Forward declarations needed for friend declarations. | 16 // Forward declarations needed for friend declarations. |
(...skipping 21 matching lines...) Expand all Loading... |
38 // (say, fewer than 64), you can efficiently pass around an EnumSet | 38 // (say, fewer than 64), you can efficiently pass around an EnumSet |
39 // for that enum around by value. | 39 // for that enum around by value. |
40 | 40 |
41 template <typename E, E MinEnumValue, E MaxEnumValue> | 41 template <typename E, E MinEnumValue, E MaxEnumValue> |
42 class EnumSet { | 42 class EnumSet { |
43 public: | 43 public: |
44 typedef E EnumType; | 44 typedef E EnumType; |
45 static const E kMinValue = MinEnumValue; | 45 static const E kMinValue = MinEnumValue; |
46 static const E kMaxValue = MaxEnumValue; | 46 static const E kMaxValue = MaxEnumValue; |
47 static const size_t kValueCount = kMaxValue - kMinValue + 1; | 47 static const size_t kValueCount = kMaxValue - kMinValue + 1; |
48 static_assert(kMinValue < kMaxValue, | 48 static_assert(kMinValue < kMaxValue, "min value must be less than max value"); |
49 "min value must be less than max value"); | |
50 | 49 |
51 private: | 50 private: |
52 // Declaration needed by Iterator. | 51 // Declaration needed by Iterator. |
53 typedef std::bitset<kValueCount> EnumBitSet; | 52 typedef std::bitset<kValueCount> EnumBitSet; |
54 | 53 |
55 public: | 54 public: |
56 // Iterator is a forward-only read-only iterator for EnumSet. Its | 55 // Iterator is a forward-only read-only iterator for EnumSet. Its |
57 // interface is deliberately distinct from an STL iterator as its | 56 // interface is deliberately distinct from an STL iterator as its |
58 // semantics are substantially different. | 57 // semantics are substantially different. |
59 // | 58 // |
(...skipping 18 matching lines...) Expand all Loading... |
78 // A default-constructed iterator can't do anything except check | 77 // A default-constructed iterator can't do anything except check |
79 // Good(). You need to call First() on an EnumSet to get a usable | 78 // Good(). You need to call First() on an EnumSet to get a usable |
80 // iterator. | 79 // iterator. |
81 Iterator() : enums_(NULL), i_(kValueCount) {} | 80 Iterator() : enums_(NULL), i_(kValueCount) {} |
82 ~Iterator() {} | 81 ~Iterator() {} |
83 | 82 |
84 // Copy constructor and assignment welcome. | 83 // Copy constructor and assignment welcome. |
85 | 84 |
86 // Returns true iff the iterator points to an EnumSet and it | 85 // Returns true iff the iterator points to an EnumSet and it |
87 // hasn't yet traversed the EnumSet entirely. | 86 // hasn't yet traversed the EnumSet entirely. |
88 bool Good() const { | 87 bool Good() const { return enums_ && i_ < kValueCount && enums_->test(i_); } |
89 return enums_ && i_ < kValueCount && enums_->test(i_); | |
90 } | |
91 | 88 |
92 // Returns the value the iterator currently points to. Good() | 89 // Returns the value the iterator currently points to. Good() |
93 // must hold. | 90 // must hold. |
94 E Get() const { | 91 E Get() const { |
95 CHECK(Good()); | 92 CHECK(Good()); |
96 return FromIndex(i_); | 93 return FromIndex(i_); |
97 } | 94 } |
98 | 95 |
99 // Moves the iterator to the next value in the EnumSet. Good() | 96 // Moves the iterator to the next value in the EnumSet. Good() |
100 // must hold. Takes linear time. | 97 // must hold. Takes linear time. |
(...skipping 16 matching lines...) Expand all Loading... |
117 } | 114 } |
118 | 115 |
119 const EnumBitSet* enums_; | 116 const EnumBitSet* enums_; |
120 size_t i_; | 117 size_t i_; |
121 }; | 118 }; |
122 | 119 |
123 // You can construct an EnumSet with 0, 1, 2, or 3 initial values. | 120 // You can construct an EnumSet with 0, 1, 2, or 3 initial values. |
124 | 121 |
125 EnumSet() {} | 122 EnumSet() {} |
126 | 123 |
127 explicit EnumSet(E value) { | 124 explicit EnumSet(E value) { Put(value); } |
128 Put(value); | |
129 } | |
130 | 125 |
131 EnumSet(E value1, E value2) { | 126 EnumSet(E value1, E value2) { |
132 Put(value1); | 127 Put(value1); |
133 Put(value2); | 128 Put(value2); |
134 } | 129 } |
135 | 130 |
136 EnumSet(E value1, E value2, E value3) { | 131 EnumSet(E value1, E value2, E value3) { |
137 Put(value1); | 132 Put(value1); |
138 Put(value2); | 133 Put(value2); |
139 Put(value3); | 134 Put(value3); |
140 } | 135 } |
141 | 136 |
142 // Returns an EnumSet with all possible values. | 137 // Returns an EnumSet with all possible values. |
143 static EnumSet All() { | 138 static EnumSet All() { |
144 EnumBitSet enums; | 139 EnumBitSet enums; |
145 enums.set(); | 140 enums.set(); |
146 return EnumSet(enums); | 141 return EnumSet(enums); |
147 } | 142 } |
148 | 143 |
149 ~EnumSet() {} | 144 ~EnumSet() {} |
150 | 145 |
151 // Copy constructor and assignment welcome. | 146 // Copy constructor and assignment welcome. |
152 | 147 |
153 // Set operations. Put, Retain, and Remove are basically | 148 // Set operations. Put, Retain, and Remove are basically |
154 // self-mutating versions of Union, Intersection, and Difference | 149 // self-mutating versions of Union, Intersection, and Difference |
155 // (defined below). | 150 // (defined below). |
156 | 151 |
157 // Adds the given value (which must be in range) to our set. | 152 // Adds the given value (which must be in range) to our set. |
158 void Put(E value) { | 153 void Put(E value) { enums_.set(ToIndex(value)); } |
159 enums_.set(ToIndex(value)); | |
160 } | |
161 | 154 |
162 // Adds all values in the given set to our set. | 155 // Adds all values in the given set to our set. |
163 void PutAll(EnumSet other) { | 156 void PutAll(EnumSet other) { enums_ |= other.enums_; } |
164 enums_ |= other.enums_; | |
165 } | |
166 | 157 |
167 // There's no real need for a Retain(E) member function. | 158 // There's no real need for a Retain(E) member function. |
168 | 159 |
169 // Removes all values not in the given set from our set. | 160 // Removes all values not in the given set from our set. |
170 void RetainAll(EnumSet other) { | 161 void RetainAll(EnumSet other) { enums_ &= other.enums_; } |
171 enums_ &= other.enums_; | |
172 } | |
173 | 162 |
174 // If the given value is in range, removes it from our set. | 163 // If the given value is in range, removes it from our set. |
175 void Remove(E value) { | 164 void Remove(E value) { |
176 if (InRange(value)) { | 165 if (InRange(value)) { |
177 enums_.reset(ToIndex(value)); | 166 enums_.reset(ToIndex(value)); |
178 } | 167 } |
179 } | 168 } |
180 | 169 |
181 // Removes all values in the given set from our set. | 170 // Removes all values in the given set from our set. |
182 void RemoveAll(EnumSet other) { | 171 void RemoveAll(EnumSet other) { enums_ &= ~other.enums_; } |
183 enums_ &= ~other.enums_; | |
184 } | |
185 | 172 |
186 // Removes all values from our set. | 173 // Removes all values from our set. |
187 void Clear() { | 174 void Clear() { enums_.reset(); } |
188 enums_.reset(); | |
189 } | |
190 | 175 |
191 // Returns true iff the given value is in range and a member of our set. | 176 // Returns true iff the given value is in range and a member of our set. |
192 bool Has(E value) const { | 177 bool Has(E value) const { |
193 return InRange(value) && enums_.test(ToIndex(value)); | 178 return InRange(value) && enums_.test(ToIndex(value)); |
194 } | 179 } |
195 | 180 |
196 // Returns true iff the given set is a subset of our set. | 181 // Returns true iff the given set is a subset of our set. |
197 bool HasAll(EnumSet other) const { | 182 bool HasAll(EnumSet other) const { |
198 return (enums_ & other.enums_) == other.enums_; | 183 return (enums_ & other.enums_) == other.enums_; |
199 } | 184 } |
200 | 185 |
201 // Returns true iff our set is empty. | 186 // Returns true iff our set is empty. |
202 bool Empty() const { | 187 bool Empty() const { return !enums_.any(); } |
203 return !enums_.any(); | |
204 } | |
205 | 188 |
206 // Returns how many values our set has. | 189 // Returns how many values our set has. |
207 size_t Size() const { | 190 size_t Size() const { return enums_.count(); } |
208 return enums_.count(); | |
209 } | |
210 | 191 |
211 // Returns an iterator pointing to the first element (if any). | 192 // Returns an iterator pointing to the first element (if any). |
212 Iterator First() const { | 193 Iterator First() const { return Iterator(enums_); } |
213 return Iterator(enums_); | |
214 } | |
215 | 194 |
216 // Returns true iff our set and the given set contain exactly the same values. | 195 // Returns true iff our set and the given set contain exactly the same values. |
217 bool operator==(const EnumSet& other) const { return enums_ == other.enums_; } | 196 bool operator==(const EnumSet& other) const { return enums_ == other.enums_; } |
218 | 197 |
219 // Returns true iff our set and the given set do not contain exactly the same | 198 // Returns true iff our set and the given set do not contain exactly the same |
220 // values. | 199 // values. |
221 bool operator!=(const EnumSet& other) const { return enums_ != other.enums_; } | 200 bool operator!=(const EnumSet& other) const { return enums_ != other.enums_; } |
222 | 201 |
223 private: | 202 private: |
224 friend EnumSet Union<E, MinEnumValue, MaxEnumValue>( | 203 friend EnumSet Union<E, MinEnumValue, MaxEnumValue>(EnumSet set1, |
225 EnumSet set1, EnumSet set2); | 204 EnumSet set2); |
226 friend EnumSet Intersection<E, MinEnumValue, MaxEnumValue>( | 205 friend EnumSet Intersection<E, MinEnumValue, MaxEnumValue>(EnumSet set1, |
227 EnumSet set1, EnumSet set2); | 206 EnumSet set2); |
228 friend EnumSet Difference<E, MinEnumValue, MaxEnumValue>( | 207 friend EnumSet Difference<E, MinEnumValue, MaxEnumValue>(EnumSet set1, |
229 EnumSet set1, EnumSet set2); | 208 EnumSet set2); |
230 | 209 |
231 explicit EnumSet(EnumBitSet enums) : enums_(enums) {} | 210 explicit EnumSet(EnumBitSet enums) : enums_(enums) {} |
232 | 211 |
233 static bool InRange(E value) { | 212 static bool InRange(E value) { |
234 return (value >= MinEnumValue) && (value <= MaxEnumValue); | 213 return (value >= MinEnumValue) && (value <= MaxEnumValue); |
235 } | 214 } |
236 | 215 |
237 // Converts a value to/from an index into |enums_|. | 216 // Converts a value to/from an index into |enums_|. |
238 | 217 |
239 static size_t ToIndex(E value) { | 218 static size_t ToIndex(E value) { |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
274 } | 253 } |
275 | 254 |
276 template <typename E, E Min, E Max> | 255 template <typename E, E Min, E Max> |
277 EnumSet<E, Min, Max> Difference(EnumSet<E, Min, Max> set1, | 256 EnumSet<E, Min, Max> Difference(EnumSet<E, Min, Max> set1, |
278 EnumSet<E, Min, Max> set2) { | 257 EnumSet<E, Min, Max> set2) { |
279 return EnumSet<E, Min, Max>(set1.enums_ & ~set2.enums_); | 258 return EnumSet<E, Min, Max>(set1.enums_ & ~set2.enums_); |
280 } | 259 } |
281 | 260 |
282 } // namespace syncer | 261 } // namespace syncer |
283 | 262 |
284 #endif // SYNC_INTERNAL_API_PUBLIC_BASE_ENUM_SET_H_ | 263 #endif // COMPONENTS_SYNC_BASE_ENUM_SET_H_ |
OLD | NEW |