15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef SYNC_INTERNAL_API_PUBLIC_BASE_ENUM_SET_H_ 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define SYNC_INTERNAL_API_PUBLIC_BASE_ENUM_SET_H_ 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <bitset> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <cstddef> 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string> 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace syncer { 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Forward declarations needed for friend declarations. 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename E, E MinEnumValue, E MaxEnumValue> 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class EnumSet; 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename E, E Min, E Max> 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)EnumSet<E, Min, Max> Union(EnumSet<E, Min, Max> set1, 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnumSet<E, Min, Max> set2); 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename E, E Min, E Max> 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)EnumSet<E, Min, Max> Intersection(EnumSet<E, Min, Max> set1, 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnumSet<E, Min, Max> set2); 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename E, E Min, E Max> 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)EnumSet<E, Min, Max> Difference(EnumSet<E, Min, Max> set1, 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnumSet<E, Min, Max> set2); 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// An EnumSet is a set that can hold enum values between a min and a 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// max value (inclusive of both). It's essentially a wrapper around 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// std::bitset<> with stronger type enforcement, more descriptive 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// member function names, and an iterator interface. 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// If you're working with enums with a small number of possible values 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (say, fewer than 64), you can efficiently pass around an EnumSet 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// for that enum around by value. 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename E, E MinEnumValue, E MaxEnumValue> 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class EnumSet { 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef E EnumType; 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const E kMinValue = MinEnumValue; 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const E kMaxValue = MaxEnumValue; 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const size_t kValueCount = kMaxValue - kMinValue + 1; 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) COMPILE_ASSERT(kMinValue < kMaxValue, 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) min_value_must_be_less_than_max_value); 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Declaration needed by Iterator. 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef std::bitset<kValueCount> EnumBitSet; 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Iterator is a forward-only read-only iterator for EnumSet. Its 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // interface is deliberately distinct from an STL iterator as its 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // semantics are substantially different. 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Example usage: 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // for (EnumSet<...>::Iterator it = enums.First(); it.Good(); it.Inc()) { 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Process(it.Get()); 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // } 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The iterator must not be outlived by the set. In particular, the 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // following is an error: 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // EnumSet<...> SomeFn() { ... } 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // /* ERROR */ 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // for (EnumSet<...>::Iterator it = SomeFun().First(); ... 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Also, there are no guarantees as to what will happen if you 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // modify an EnumSet while traversing it with an iterator. 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) class Iterator { 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // A default-constructed iterator can't do anything except check 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Good(). You need to call First() on an EnumSet to get a usable 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // iterator. 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Iterator() : enums_(NULL), i_(kValueCount) {} 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ~Iterator() {} 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Copy constructor and assignment welcome. 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns true iff the iterator points to an EnumSet and it 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // hasn't yet traversed the EnumSet entirely. 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool Good() const { 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return enums_ && i_ < kValueCount && enums_->test(i_); 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns the value the iterator currently points to. Good() 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // must hold. 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) E Get() const { 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(Good()); 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FromIndex(i_); 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Moves the iterator to the next value in the EnumSet. Good() 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // must hold. Takes linear time. 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Inc() { 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(Good()); 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i_ = FindNext(i_ + 1); 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) friend Iterator EnumSet::First() const; 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) explicit Iterator(const EnumBitSet& enums) 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : enums_(&enums), i_(FindNext(0)) {} 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t FindNext(size_t i) { 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while ((i < kValueCount) && !enums_->test(i)) { 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++i; 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return i; 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const EnumBitSet* enums_; 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t i_; 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // You can construct an EnumSet with 0, 1, 2, or 3 initial values. 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnumSet() {} 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) explicit EnumSet(E value) { 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Put(value); 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnumSet(E value1, E value2) { 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Put(value1); 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Put(value2); 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnumSet(E value1, E value2, E value3) { 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Put(value1); 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Put(value2); 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Put(value3); 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns an EnumSet with all possible values. 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static EnumSet All() { 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnumBitSet enums; 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) enums.set(); 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return EnumSet(enums); 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ~EnumSet() {} 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Copy constructor and assignment welcome. 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Set operations. Put, Retain, and Remove are basically 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // self-mutating versions of Union, Intersection, and Difference 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // (defined below). 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Adds the given value (which must be in range) to our set. 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Put(E value) { 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) enums_.set(ToIndex(value)); 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Adds all values in the given set to our set. 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void PutAll(EnumSet other) { 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) enums_ |= other.enums_; 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // There's no real need for a Retain(E) member function. 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Removes all values not in the given set from our set. 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void RetainAll(EnumSet other) { 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) enums_ &= other.enums_; 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the given value is in range, removes it from our set. 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Remove(E value) { 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (InRange(value)) { 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) enums_.reset(ToIndex(value)); 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Removes all values in the given set from our set. 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void RemoveAll(EnumSet other) { 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) enums_ &= ~other.enums_; 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Removes all values from our set. 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Clear() { 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) enums_.reset(); 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns true iff the given value is in range and a member of our 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // set. 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool Has(E value) const { 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return InRange(value) && enums_.test(ToIndex(value)); 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns true iff the given set is a subset of our set. 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool HasAll(EnumSet other) const { 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (enums_ & other.enums_) == other.enums_; 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns true iff our set and the given set contain exactly the 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // same values. 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool Equals(const EnumSet& other) const { 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return enums_ == other.enums_; 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns true iff our set is empty. 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool Empty() const { 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return !enums_.any(); 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns how many values our set has. 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t Size() const { 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return enums_.count(); 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns an iterator pointing to the first element (if any). 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Iterator First() const { 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Iterator(enums_); 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) friend EnumSet Union<E, MinEnumValue, MaxEnumValue>( 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnumSet set1, EnumSet set2); 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) friend EnumSet Intersection<E, MinEnumValue, MaxEnumValue>( 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnumSet set1, EnumSet set2); 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) friend EnumSet Difference<E, MinEnumValue, MaxEnumValue>( 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnumSet set1, EnumSet set2); 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) explicit EnumSet(EnumBitSet enums) : enums_(enums) {} 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static bool InRange(E value) { 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (value >= MinEnumValue) && (value <= MaxEnumValue); 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Converts a value to/from an index into |enums_|. 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static size_t ToIndex(E value) { 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_GE(value, MinEnumValue); 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_LE(value, MaxEnumValue); 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return value - MinEnumValue; 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static E FromIndex(size_t i) { 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_LT(i, kValueCount); 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return static_cast<E>(MinEnumValue + i); 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnumBitSet enums_; 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename E, E MinEnumValue, E MaxEnumValue> 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const E EnumSet<E, MinEnumValue, MaxEnumValue>::kMinValue; 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename E, E MinEnumValue, E MaxEnumValue> 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const E EnumSet<E, MinEnumValue, MaxEnumValue>::kMaxValue; 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename E, E MinEnumValue, E MaxEnumValue> 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const size_t EnumSet<E, MinEnumValue, MaxEnumValue>::kValueCount; 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The usual set operations. 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename E, E Min, E Max> 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)EnumSet<E, Min, Max> Union(EnumSet<E, Min, Max> set1, 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnumSet<E, Min, Max> set2) { 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return EnumSet<E, Min, Max>(set1.enums_ | set2.enums_); 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename E, E Min, E Max> 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)EnumSet<E, Min, Max> Intersection(EnumSet<E, Min, Max> set1, 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnumSet<E, Min, Max> set2) { 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return EnumSet<E, Min, Max>(set1.enums_ & set2.enums_); 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename E, E Min, E Max> 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)EnumSet<E, Min, Max> Difference(EnumSet<E, Min, Max> set1, 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnumSet<E, Min, Max> set2) { 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return EnumSet<E, Min, Max>(set1.enums_ & ~set2.enums_); 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace syncer 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // SYNC_INTERNAL_API_PUBLIC_BASE_ENUM_SET_H_ 286