OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #ifndef BASE_SET_TEMPLATE_H_ |
| 6 #define BASE_SET_TEMPLATE_H_ |
| 7 |
| 8 #include <initializer_list> |
| 9 #include <type_traits> |
| 10 |
| 11 namespace base { |
| 12 |
| 13 template <class T, unsigned char maxEl> |
| 14 class SetCore { |
| 15 public: |
| 16 typedef |
| 17 typename std::conditional<((maxEl / 8 + 1) == 1), unsigned char, |
| 18 typename std::conditional<((maxEl / 8 + 1) == 2), unsigned short, |
| 19 unsigned int>::type>::type _Ty; |
| 20 |
| 21 private: |
| 22 static_assert(std::is_enum<T>::value, "T must be an enumeration"); |
| 23 static_assert(maxEl < 32, "Sets can only contain up to 32 elements"); |
| 24 |
| 25 protected: |
| 26 SetCore() : data(0) {} |
| 27 |
| 28 public: |
| 29 _Ty data; |
| 30 }; |
| 31 |
| 32 template <class T, T maxEl> |
| 33 class SetOf : public SetCore<T, static_cast<unsigned char>(maxEl)> { |
| 34 static constexpr unsigned char NumElms = |
| 35 static_cast<unsigned char>(maxEl) + 1; |
| 36 static constexpr unsigned char MaxEl = NumElms - 1; |
| 37 |
| 38 public: |
| 39 class ElemRef { |
| 40 friend class SetOf<T, maxEl>; |
| 41 public: |
| 42 ~ElemRef() {} |
| 43 |
| 44 ElemRef& operator=(bool rhs) { |
| 45 if (rhs) |
| 46 set_->Include(el_); |
| 47 else |
| 48 set_->Exclude(el_); |
| 49 return *this; |
| 50 } |
| 51 |
| 52 ElemRef& operator=(const ElemRef& elemref) { |
| 53 return set_->operator=(bool(elemref)); |
| 54 } |
| 55 |
| 56 operator bool() const { |
| 57 return set_->Contains(el_); |
| 58 } |
| 59 |
| 60 private: |
| 61 ElemRef() : set_(nullptr), el_(static_cast<T>(0)) {} |
| 62 ElemRef(SetOf<T, maxEl>& set, T el) : set_(&set), el_(el) {} |
| 63 |
| 64 SetOf<T, maxEl>* set_; |
| 65 T el_; |
| 66 }; |
| 67 |
| 68 SetOf() : SetCore<T, MaxEl>() {} |
| 69 |
| 70 SetOf(const SetOf& src) : SetCore<T, MaxEl>() { |
| 71 this->data = src.data; |
| 72 } |
| 73 |
| 74 explicit SetOf(const int& src) : SetCore<T, MaxEl>() { |
| 75 union { |
| 76 typename SetCore<T, MaxEl>::_Ty data; |
| 77 unsigned int IntData; |
| 78 } overlay; |
| 79 overlay.IntData = src; |
| 80 this->data = overlay.data; |
| 81 } |
| 82 |
| 83 SetOf(const std::initializer_list<T>& src) : SetCore<T, MaxEl>() { |
| 84 Include(src); |
| 85 } |
| 86 |
| 87 SetOf& operator=(const SetOf& rhs) { |
| 88 if (this != &rhs) |
| 89 this->data = rhs.data; |
| 90 return *this; |
| 91 } |
| 92 |
| 93 SetOf& operator+=(const SetOf& rhs) { |
| 94 this->data |= rhs.data; |
| 95 return *this; |
| 96 } |
| 97 |
| 98 SetOf& operator-=(const SetOf& rhs) { |
| 99 this->data ^= rhs.data; |
| 100 return *this; |
| 101 } |
| 102 |
| 103 SetOf& operator*=(const SetOf& rhs) { |
| 104 this->data &= rhs.data; |
| 105 return *this; |
| 106 } |
| 107 |
| 108 SetOf operator+(const SetOf& rhs) { |
| 109 SetOf<T, maxEl> s; |
| 110 s.data = this->data | rhs.data; |
| 111 return s; |
| 112 } |
| 113 |
| 114 SetOf operator-(const SetOf& rhs) { |
| 115 SetOf<T, maxEl> s; |
| 116 s.data = this->data ^ rhs.data; |
| 117 return s; |
| 118 } |
| 119 |
| 120 SetOf operator*(const SetOf& rhs) { |
| 121 SetOf<T, maxEl> s; |
| 122 s.data = this->data & rhs.data; |
| 123 return s; |
| 124 } |
| 125 |
| 126 SetOf& operator<<(const T el) { |
| 127 return Include(el); |
| 128 } |
| 129 |
| 130 SetOf& operator>>(const T el) { |
| 131 return Exclude(el); |
| 132 } |
| 133 |
| 134 bool operator==(const SetOf& rhs) const { |
| 135 static const typename SetCore<T, MaxEl>::_Ty Mask = |
| 136 static_cast<typename SetCore<T, MaxEl>::_Ty>(-1) >> |
| 137 (sizeof(this->data) * 8 - NumElms); |
| 138 return !(this->data != rhs.data && |
| 139 (Mask & this->data) != (Mask & rhs.data)); |
| 140 } |
| 141 |
| 142 bool operator!=(const SetOf& rhs) const { |
| 143 return !operator==(rhs); |
| 144 } |
| 145 |
| 146 constexpr bool operator[](const T el) const { |
| 147 return Contains(el); |
| 148 } |
| 149 |
| 150 ElemRef operator[](T el) { |
| 151 return ElemRef(*this, el); |
| 152 } |
| 153 |
| 154 SetOf& Clear() { |
| 155 this->data = 0; |
| 156 return *this; |
| 157 } |
| 158 |
| 159 bool Contains(const T el) const { |
| 160 return static_cast<int>(el) >= 0 && static_cast<int>(el) < NumElms && |
| 161 (this->data & static_cast<int>(1) << static_cast<int>(el)) != 0; |
| 162 } |
| 163 |
| 164 bool ContainsAll(const std::initializer_list<T>& els) const { |
| 165 for (const T& el : els) |
| 166 if (!Contains(el)) |
| 167 return false; |
| 168 return true; |
| 169 } |
| 170 |
| 171 bool ContainsSome(const std::initializer_list<T>& els) const { |
| 172 for (const T& el : els) |
| 173 if (Contains(el)) |
| 174 return true; |
| 175 return false; |
| 176 } |
| 177 |
| 178 bool Equals(const std::initializer_list<T>& rhs) const { |
| 179 SetOf<T, maxEl> s(rhs); |
| 180 return operator==(s); |
| 181 } |
| 182 |
| 183 bool Equals(const std::initializer_list<T>& mask, |
| 184 const std::initializer_list<T>& rhs) const { |
| 185 SetOf<T, maxEl> s_mask(mask); |
| 186 SetOf<T, maxEl> s_rhs(rhs); |
| 187 return (s_mask * *this) == s_rhs; |
| 188 } |
| 189 |
| 190 bool Equals(const SetOf& mask, |
| 191 const std::initializer_list<T>& rhs) const { |
| 192 SetOf<T, maxEl> s_rhs(rhs); |
| 193 return (mask * *this) == s_rhs; |
| 194 } |
| 195 |
| 196 bool Equals(const SetOf& rhs) const { |
| 197 return *this == rhs; |
| 198 } |
| 199 |
| 200 SetOf& Exclude(const T el) { |
| 201 if (static_cast<int>(el) >= 0 && static_cast<int>(el) < NumElms) |
| 202 this->data &= ~(static_cast<int>(1) << static_cast<int>(el)); |
| 203 return *this; |
| 204 } |
| 205 |
| 206 SetOf& Exclude(const std::initializer_list<T>& els) { |
| 207 for (const T& el : els) |
| 208 Exclude(el); |
| 209 return *this; |
| 210 } |
| 211 |
| 212 SetOf& Include(const T el) { |
| 213 if (static_cast<int>(el) >= 0 && static_cast<int>(el) < NumElms) |
| 214 this->data |= (static_cast<int>(1) << static_cast<int>(el)); |
| 215 return *this; |
| 216 } |
| 217 |
| 218 SetOf& Include(const std::initializer_list<T>& els) { |
| 219 for (const T& el : els) |
| 220 Include(el); |
| 221 return *this; |
| 222 } |
| 223 |
| 224 bool IsEmpty() const { return this->data == 0; } |
| 225 }; |
| 226 |
| 227 } // namespace base |
| 228 |
| 229 #endif // BASE_SET_TEMPLATE_H_ |
OLD | NEW |