| Index: base/set_template.h | 
| diff --git a/base/set_template.h b/base/set_template.h | 
| new file mode 100644 | 
| index 0000000000000000000000000000000000000000..3b67d4507f3da6627a7b02a2c6a4dc3f468e85e9 | 
| --- /dev/null | 
| +++ b/base/set_template.h | 
| @@ -0,0 +1,229 @@ | 
| +// Copyright (c) 2016 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 BASE_SET_TEMPLATE_H_ | 
| +#define BASE_SET_TEMPLATE_H_ | 
| + | 
| +#include <initializer_list> | 
| +#include <type_traits> | 
| + | 
| +namespace base { | 
| + | 
| +template <class T, unsigned char maxEl> | 
| +class SetCore { | 
| + public: | 
| +  typedef | 
| +      typename std::conditional<((maxEl / 8 + 1) == 1), unsigned char, | 
| +      typename std::conditional<((maxEl / 8 + 1) == 2), unsigned short, | 
| +      unsigned int>::type>::type _Ty; | 
| + | 
| + private: | 
| +  static_assert(std::is_enum<T>::value, "T must be an enumeration"); | 
| +  static_assert(maxEl < 32, "Sets can only contain up to 32 elements"); | 
| + | 
| + protected: | 
| +  SetCore() : data(0) {} | 
| + | 
| + public: | 
| +  _Ty data; | 
| +}; | 
| + | 
| +template <class T, T maxEl> | 
| +class SetOf : public SetCore<T, static_cast<unsigned char>(maxEl)> { | 
| +  static constexpr unsigned char NumElms = | 
| +      static_cast<unsigned char>(maxEl) + 1; | 
| +  static constexpr unsigned char MaxEl = NumElms - 1; | 
| + | 
| + public: | 
| +  class ElemRef { | 
| +    friend class SetOf<T, maxEl>; | 
| +   public: | 
| +    ~ElemRef() {} | 
| + | 
| +    ElemRef& operator=(bool rhs) { | 
| +      if (rhs) | 
| +        set_->Include(el_); | 
| +      else | 
| +        set_->Exclude(el_); | 
| +      return *this; | 
| +    } | 
| + | 
| +    ElemRef& operator=(const ElemRef& elemref) { | 
| +      return set_->operator=(bool(elemref)); | 
| +    } | 
| + | 
| +    operator bool() const { | 
| +      return set_->Contains(el_); | 
| +    } | 
| + | 
| +   private: | 
| +    ElemRef() : set_(nullptr), el_(static_cast<T>(0)) {} | 
| +    ElemRef(SetOf<T, maxEl>& set, T el) : set_(&set), el_(el)  {} | 
| + | 
| +    SetOf<T, maxEl>* set_; | 
| +    T el_; | 
| +  }; | 
| + | 
| +  SetOf() : SetCore<T, MaxEl>() {} | 
| + | 
| +  SetOf(const SetOf& src) : SetCore<T, MaxEl>() { | 
| +    this->data = src.data; | 
| +  } | 
| + | 
| +  explicit SetOf(const int& src) : SetCore<T, MaxEl>() { | 
| +    union { | 
| +      typename SetCore<T, MaxEl>::_Ty data; | 
| +      unsigned int IntData; | 
| +    } overlay; | 
| +    overlay.IntData = src; | 
| +    this->data = overlay.data; | 
| +  } | 
| + | 
| +  SetOf(const std::initializer_list<T>& src) : SetCore<T, MaxEl>() { | 
| +    Include(src); | 
| +  } | 
| + | 
| +  SetOf& operator=(const SetOf& rhs) { | 
| +    if (this != &rhs) | 
| +      this->data = rhs.data; | 
| +    return *this; | 
| +  } | 
| + | 
| +  SetOf& operator+=(const SetOf& rhs) { | 
| +    this->data |= rhs.data; | 
| +    return *this; | 
| +  } | 
| + | 
| +  SetOf& operator-=(const SetOf& rhs) { | 
| +    this->data ^= rhs.data; | 
| +    return *this; | 
| +  } | 
| + | 
| +  SetOf& operator*=(const SetOf& rhs) { | 
| +    this->data &= rhs.data; | 
| +    return *this; | 
| +  } | 
| + | 
| +  SetOf operator+(const SetOf& rhs) { | 
| +    SetOf<T, maxEl> s; | 
| +    s.data = this->data | rhs.data; | 
| +    return s; | 
| +  } | 
| + | 
| +  SetOf operator-(const SetOf& rhs) { | 
| +    SetOf<T, maxEl> s; | 
| +    s.data = this->data ^ rhs.data; | 
| +    return s; | 
| +  } | 
| + | 
| +  SetOf operator*(const SetOf& rhs) { | 
| +    SetOf<T, maxEl> s; | 
| +    s.data = this->data & rhs.data; | 
| +    return s; | 
| +  } | 
| + | 
| +  SetOf& operator<<(const T el) { | 
| +    return Include(el); | 
| +  } | 
| + | 
| +  SetOf& operator>>(const T el) { | 
| +    return Exclude(el); | 
| +  } | 
| + | 
| +  bool operator==(const SetOf& rhs) const { | 
| +    static const typename SetCore<T, MaxEl>::_Ty Mask = | 
| +        static_cast<typename SetCore<T, MaxEl>::_Ty>(-1) >> | 
| +          (sizeof(this->data) * 8 - NumElms); | 
| +    return !(this->data != rhs.data && | 
| +        (Mask & this->data) != (Mask & rhs.data)); | 
| +  } | 
| + | 
| +  bool operator!=(const SetOf& rhs) const { | 
| +    return !operator==(rhs); | 
| +  } | 
| + | 
| +  constexpr bool operator[](const T el) const { | 
| +    return Contains(el); | 
| +  } | 
| + | 
| +  ElemRef operator[](T el) { | 
| +    return ElemRef(*this, el); | 
| +  } | 
| + | 
| +  SetOf& Clear() { | 
| +    this->data = 0; | 
| +    return *this; | 
| +  } | 
| + | 
| +  bool Contains(const T el) const { | 
| +    return static_cast<int>(el) >= 0 && static_cast<int>(el) < NumElms && | 
| +           (this->data & static_cast<int>(1) << static_cast<int>(el)) != 0; | 
| +  } | 
| + | 
| +  bool ContainsAll(const std::initializer_list<T>& els) const { | 
| +    for (const T& el : els) | 
| +      if (!Contains(el)) | 
| +        return false; | 
| +    return true; | 
| +  } | 
| + | 
| +  bool ContainsSome(const std::initializer_list<T>& els) const { | 
| +    for (const T& el : els) | 
| +      if (Contains(el)) | 
| +        return true; | 
| +    return false; | 
| +  } | 
| + | 
| +  bool Equals(const std::initializer_list<T>& rhs) const { | 
| +    SetOf<T, maxEl> s(rhs); | 
| +    return operator==(s); | 
| +  } | 
| + | 
| +  bool Equals(const std::initializer_list<T>& mask, | 
| +              const std::initializer_list<T>& rhs) const { | 
| +    SetOf<T, maxEl> s_mask(mask); | 
| +    SetOf<T, maxEl> s_rhs(rhs); | 
| +    return (s_mask * *this) == s_rhs; | 
| +  } | 
| + | 
| +  bool Equals(const SetOf& mask, | 
| +              const std::initializer_list<T>& rhs) const { | 
| +    SetOf<T, maxEl> s_rhs(rhs); | 
| +    return (mask * *this) == s_rhs; | 
| +  } | 
| + | 
| +  bool Equals(const SetOf& rhs) const { | 
| +    return *this == rhs; | 
| +  } | 
| + | 
| +  SetOf& Exclude(const T el) { | 
| +    if (static_cast<int>(el) >= 0 && static_cast<int>(el) < NumElms) | 
| +      this->data &= ~(static_cast<int>(1) << static_cast<int>(el)); | 
| +    return *this; | 
| +  } | 
| + | 
| +  SetOf& Exclude(const std::initializer_list<T>& els) { | 
| +    for (const T& el : els) | 
| +      Exclude(el); | 
| +    return *this; | 
| +  } | 
| + | 
| +  SetOf& Include(const T el) { | 
| +    if (static_cast<int>(el) >= 0 && static_cast<int>(el) < NumElms) | 
| +      this->data |= (static_cast<int>(1) << static_cast<int>(el)); | 
| +    return *this; | 
| +  } | 
| + | 
| +  SetOf& Include(const std::initializer_list<T>& els) { | 
| +    for (const T& el : els) | 
| +      Include(el); | 
| +    return *this; | 
| +  } | 
| + | 
| +  bool IsEmpty() const { return this->data == 0; } | 
| +}; | 
| + | 
| +} // namespace base | 
| + | 
| +#endif  // BASE_SET_TEMPLATE_H_ | 
|  |