| Index: chrome/browser/sync/util/enum_set.h
|
| diff --git a/chrome/browser/sync/util/enum_set.h b/chrome/browser/sync/util/enum_set.h
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..d12712267f22d9298e04a4820b8022a6a93025a4
|
| --- /dev/null
|
| +++ b/chrome/browser/sync/util/enum_set.h
|
| @@ -0,0 +1,271 @@
|
| +// Copyright (c) 2011 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#ifndef CHROME_BROWSER_SYNC_UTIL_ENUM_SET_H_
|
| +#define CHROME_BROWSER_SYNC_UTIL_ENUM_SET_H_
|
| +#pragma once
|
| +
|
| +#include <bitset>
|
| +#include <cstddef>
|
| +#include <string>
|
| +
|
| +#include "base/basictypes.h"
|
| +#include "base/logging.h"
|
| +
|
| +namespace browser_sync {
|
| +
|
| +// Forward declarations needed for friend declarations.
|
| +template <typename E, E MinEnumValue, E MaxEnumValue>
|
| +class EnumSet;
|
| +
|
| +template <typename E, E Min, E Max>
|
| +EnumSet<E, Min, Max> Union(EnumSet<E, Min, Max> set1,
|
| + EnumSet<E, Min, Max> set2);
|
| +
|
| +template <typename E, E Min, E Max>
|
| +EnumSet<E, Min, Max> Intersection(EnumSet<E, Min, Max> set1,
|
| + EnumSet<E, Min, Max> set2);
|
| +
|
| +template <typename E, E Min, E Max>
|
| +EnumSet<E, Min, Max> Difference(EnumSet<E, Min, Max> set1,
|
| + EnumSet<E, Min, Max> set2);
|
| +
|
| +// An EnumSet is a set that can hold enum values between a min and a
|
| +// max value (inclusive of both). It's essentially a wrapper around
|
| +// std::bitset<> with stronger type enforcement, more descriptive
|
| +// member function names, and an iterator interface.
|
| +//
|
| +// If you're working with enums with a small number of possible values
|
| +// (say, fewer than 64), you can efficiently pass around an EnumSet
|
| +// for that enum around by value.
|
| +
|
| +template <typename E, E MinEnumValue, E MaxEnumValue>
|
| +class EnumSet {
|
| + public:
|
| + typedef E EnumType;
|
| + static const E kMinValue = MinEnumValue;
|
| + static const E kMaxValue = MaxEnumValue;
|
| + static const size_t kValueCount = kMaxValue - kMinValue + 1;
|
| + COMPILE_ASSERT(kMinValue < kMaxValue,
|
| + min_value_must_be_less_than_max_value);
|
| +
|
| + private:
|
| + // Declaration needed by Iterator.
|
| + typedef std::bitset<kValueCount> EnumBitSet;
|
| +
|
| + public:
|
| + // Iterator is a forward-only read-only iterator for EnumSet. Its
|
| + // interface is deliberately distinct from an STL iterator as its
|
| + // semantics are substantially different.
|
| + //
|
| + // Example usage:
|
| + //
|
| + // for (EnumSet<...>::Iterator it = enums.First(); it.Good(); it.Inc()) {
|
| + // Process(it.Get());
|
| + // }
|
| + //
|
| + // There are no guarantees as to what will happen if you modify an
|
| + // EnumSet while traversing it with an iterator.
|
| + class Iterator {
|
| + public:
|
| + // A default-constructed iterator can't do anything except check
|
| + // Good(). You need to call First() on an EnumSet to get a usable
|
| + // iterator.
|
| + Iterator() : enums_(NULL), i_(kValueCount) {}
|
| + ~Iterator() {}
|
| +
|
| + // Copy constructor and assignment welcome.
|
| +
|
| + // Returns true iff the iterator points to an EnumSet and it
|
| + // hasn't yet traversed the EnumSet entirely.
|
| + bool Good() const {
|
| + return enums_ && i_ < kValueCount && enums_->test(i_);
|
| + }
|
| +
|
| + // Returns the value the iterator currently points to. Good()
|
| + // must hold.
|
| + E Get() const {
|
| + CHECK(Good());
|
| + return FromIndex(i_);
|
| + }
|
| +
|
| + // Moves the iterator to the next value in the EnumSet. Good()
|
| + // must hold. Takes linear time.
|
| + void Inc() {
|
| + CHECK(Good());
|
| + i_ = FindNext(i_ + 1);
|
| + }
|
| +
|
| + private:
|
| + friend Iterator EnumSet::First() const;
|
| +
|
| + explicit Iterator(const EnumBitSet& enums)
|
| + : enums_(&enums), i_(FindNext(0)) {}
|
| +
|
| + size_t FindNext(size_t i) {
|
| + while ((i < kValueCount) && !enums_->test(i)) {
|
| + ++i;
|
| + }
|
| + return i;
|
| + }
|
| +
|
| + const EnumBitSet* enums_;
|
| + size_t i_;
|
| + };
|
| +
|
| + // You can construct an EnumSet with 0, 1, 2, or 3 initial values.
|
| +
|
| + EnumSet() {}
|
| +
|
| + explicit EnumSet(E value) {
|
| + Put(value);
|
| + }
|
| +
|
| + EnumSet(E value1, E value2) {
|
| + Put(value1);
|
| + Put(value2);
|
| + }
|
| +
|
| + EnumSet(E value1, E value2, E value3) {
|
| + Put(value1);
|
| + Put(value2);
|
| + Put(value3);
|
| + }
|
| +
|
| + // Returns an EnumSet with all possible values.
|
| + static EnumSet All() {
|
| + EnumBitSet enums;
|
| + enums.set();
|
| + return EnumSet(enums);
|
| + }
|
| +
|
| + ~EnumSet() {}
|
| +
|
| + // Copy constructor and assignment welcome.
|
| +
|
| + // Set operations. Put, Retain, and Remove are basically
|
| + // self-mutating versions of Union, Intersection, and Difference
|
| + // (defined below).
|
| +
|
| + // Adds the given value to our set.
|
| + void Put(E value) {
|
| + enums_.set(ToIndex(value));
|
| + }
|
| +
|
| + // Adds all values in the given set to our set.
|
| + void PutAll(EnumSet other) {
|
| + enums_ |= other.enums_;
|
| + }
|
| +
|
| + // There's no real need for a Retain(E) member function.
|
| +
|
| + // Removes all values not in the given set from our set.
|
| + void RetainAll(EnumSet other) {
|
| + enums_ &= other.enums_;
|
| + }
|
| +
|
| + // Removes the given value from our set.
|
| + void Remove(E value) {
|
| + enums_.reset(ToIndex(value));
|
| + }
|
| +
|
| + // Removes all values in the given set from our set.
|
| + void RemoveAll(EnumSet other) {
|
| + enums_ &= ~other.enums_;
|
| + }
|
| +
|
| + // Removes all values from our set.
|
| + void Clear() {
|
| + enums_.reset();
|
| + }
|
| +
|
| + // Returns true iff the given value is a member of our set.
|
| + bool Has(E value) const {
|
| + return enums_.test(ToIndex(value));
|
| + }
|
| +
|
| + // Returns true iff the given set is a subset of our set.
|
| + bool HasAll(EnumSet other) const {
|
| + return (enums_ & other.enums_) == other.enums_;
|
| + }
|
| +
|
| + // Returns true iff our set and the given set contain exactly the
|
| + // same values.
|
| + bool Equals(const EnumSet& other) const {
|
| + return enums_ == other.enums_;
|
| + }
|
| +
|
| + // Returns true iff our set is empty.
|
| + bool Empty() const {
|
| + return !enums_.any();
|
| + }
|
| +
|
| + // Returns how many values our set has.
|
| + size_t Size() const {
|
| + return enums_.count();
|
| + }
|
| +
|
| + // Returns an iterator pointing to the first element (if any).
|
| + Iterator First() const {
|
| + return Iterator(enums_);
|
| + }
|
| +
|
| + private:
|
| + friend EnumSet Union<E, MinEnumValue, MaxEnumValue>(
|
| + EnumSet set1, EnumSet set2);
|
| + friend EnumSet Intersection<E, MinEnumValue, MaxEnumValue>(
|
| + EnumSet set1, EnumSet set2);
|
| + friend EnumSet Difference<E, MinEnumValue, MaxEnumValue>(
|
| + EnumSet set1, EnumSet set2);
|
| +
|
| + explicit EnumSet(EnumBitSet enums) : enums_(enums) {}
|
| +
|
| + // Converts a value to/from an index into |enums_|.
|
| +
|
| + static size_t ToIndex(E value) {
|
| + DCHECK_GE(value, MinEnumValue);
|
| + DCHECK_LE(value, MaxEnumValue);
|
| + return value - MinEnumValue;
|
| + }
|
| +
|
| + static E FromIndex(size_t i) {
|
| + DCHECK_LT(i, kValueCount);
|
| + return static_cast<E>(MinEnumValue + i);
|
| + }
|
| +
|
| + EnumBitSet enums_;
|
| +};
|
| +
|
| +template <typename E, E MinEnumValue, E MaxEnumValue>
|
| +const E EnumSet<E, MinEnumValue, MaxEnumValue>::kMinValue;
|
| +
|
| +template <typename E, E MinEnumValue, E MaxEnumValue>
|
| +const E EnumSet<E, MinEnumValue, MaxEnumValue>::kMaxValue;
|
| +
|
| +template <typename E, E MinEnumValue, E MaxEnumValue>
|
| +const size_t EnumSet<E, MinEnumValue, MaxEnumValue>::kValueCount;
|
| +
|
| +// The usual set operations.
|
| +
|
| +template <typename E, E Min, E Max>
|
| +EnumSet<E, Min, Max> Union(EnumSet<E, Min, Max> set1,
|
| + EnumSet<E, Min, Max> set2) {
|
| + return EnumSet<E, Min, Max>(set1.enums_ | set2.enums_);
|
| +}
|
| +
|
| +template <typename E, E Min, E Max>
|
| +EnumSet<E, Min, Max> Intersection(EnumSet<E, Min, Max> set1,
|
| + EnumSet<E, Min, Max> set2) {
|
| + return EnumSet<E, Min, Max>(set1.enums_ & set2.enums_);
|
| +}
|
| +
|
| +template <typename E, E Min, E Max>
|
| +EnumSet<E, Min, Max> Difference(EnumSet<E, Min, Max> set1,
|
| + EnumSet<E, Min, Max> set2) {
|
| + return EnumSet<E, Min, Max>(set1.enums_ & ~set2.enums_);
|
| +}
|
| +
|
| +} // namespace browser_sync
|
| +
|
| +#endif // CHROME_BROWSER_SYNC_UTIL_ENUM_SET_H_
|
|
|