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_ |