mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-05-13 10:51:35 +00:00
This PR condenses the namespaces in the tint/utils folder. Change-Id: I6b541a6383386346a0b11ba46074a5981fe75f66 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/86028 Auto-Submit: Dan Sinclair <dsinclair@chromium.org> Reviewed-by: Ben Clayton <bclayton@google.com> Commit-Queue: Dan Sinclair <dsinclair@chromium.org>
257 lines
7.4 KiB
C++
257 lines
7.4 KiB
C++
// Copyright 2021 The Tint Authors.
|
||
//
|
||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||
// you may not use this file except in compliance with the License.
|
||
// You may obtain a copy of the License at
|
||
//
|
||
// http://www.apache.org/licenses/LICENSE-2.0
|
||
//
|
||
// Unless required by applicable law or agreed to in writing, software
|
||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
// See the License for the specific language governing permissions and
|
||
// limitations under the License.
|
||
|
||
#ifndef SRC_TINT_UTILS_ENUM_SET_H_
|
||
#define SRC_TINT_UTILS_ENUM_SET_H_
|
||
|
||
#include <cstdint>
|
||
#include <functional>
|
||
#include <ostream>
|
||
#include <type_traits>
|
||
#include <utility>
|
||
|
||
namespace tint::utils {
|
||
|
||
/// EnumSet is a set of enum values.
|
||
/// @note As the EnumSet is backed by a single uint64_t value, it can only hold
|
||
/// enum values in the range [0 .. 63].
|
||
template <typename ENUM>
|
||
struct EnumSet {
|
||
public:
|
||
/// Enum is the enum type this EnumSet wraps
|
||
using Enum = ENUM;
|
||
|
||
/// Constructor. Initializes the EnumSet with zero.
|
||
constexpr EnumSet() = default;
|
||
|
||
/// Copy constructor.
|
||
/// @param s the set to copy
|
||
constexpr EnumSet(const EnumSet& s) = default;
|
||
|
||
/// Constructor. Initializes the EnumSet with the given values.
|
||
/// @param values the enumerator values to construct the set with
|
||
template <typename... VALUES>
|
||
explicit constexpr EnumSet(VALUES... values) : set(Union(values...)) {}
|
||
|
||
/// Copy assignment operator.
|
||
/// @param set the set to assign to this set
|
||
/// @return this set so calls can be chained
|
||
inline EnumSet& operator=(const EnumSet& set) = default;
|
||
|
||
/// Copy assignment operator.
|
||
/// @param e the enum value
|
||
/// @return this set so calls can be chained
|
||
inline EnumSet& operator=(Enum e) { return *this = EnumSet{e}; }
|
||
|
||
/// Adds all the given values to this set
|
||
/// @param values the values to add
|
||
/// @return this set so calls can be chained
|
||
template <typename... VALUES>
|
||
inline EnumSet& Add(VALUES... values) {
|
||
return Add(EnumSet(std::forward<VALUES>(values)...));
|
||
}
|
||
|
||
/// Removes all the given values from this set
|
||
/// @param values the values to remove
|
||
/// @return this set so calls can be chained
|
||
template <typename... VALUES>
|
||
inline EnumSet& Remove(VALUES... values) {
|
||
return Remove(EnumSet(std::forward<VALUES>(values)...));
|
||
}
|
||
|
||
/// Adds all of s to this set
|
||
/// @param s the enum value
|
||
/// @return this set so calls can be chained
|
||
inline EnumSet& Add(EnumSet s) { return (*this = *this + s); }
|
||
|
||
/// Removes all of s from this set
|
||
/// @param s the enum value
|
||
/// @return this set so calls can be chained
|
||
inline EnumSet& Remove(EnumSet s) { return (*this = *this - s); }
|
||
|
||
/// @param e the enum value
|
||
/// @returns a copy of this set with e added
|
||
inline EnumSet operator+(Enum e) const {
|
||
EnumSet out;
|
||
out.set = set | Bit(e);
|
||
return out;
|
||
}
|
||
|
||
/// @param e the enum value
|
||
/// @returns a copy of this set with e removed
|
||
inline EnumSet operator-(Enum e) const {
|
||
EnumSet out;
|
||
out.set = set & ~Bit(e);
|
||
return out;
|
||
}
|
||
|
||
/// @param s the other set
|
||
/// @returns the union of this set with s (this ∪ rhs)
|
||
inline EnumSet operator+(EnumSet s) const {
|
||
EnumSet out;
|
||
out.set = set | s.set;
|
||
return out;
|
||
}
|
||
|
||
/// @param s the other set
|
||
/// @returns the set of entries found in this but not in s (this \ s)
|
||
inline EnumSet operator-(EnumSet s) const {
|
||
EnumSet out;
|
||
out.set = set & ~s.set;
|
||
return out;
|
||
}
|
||
|
||
/// @param s the other set
|
||
/// @returns the intersection of this set with s (this ∩ rhs)
|
||
inline EnumSet operator&(EnumSet s) const {
|
||
EnumSet out;
|
||
out.set = set & s.set;
|
||
return out;
|
||
}
|
||
|
||
/// @param e the enum value
|
||
/// @return true if the set contains `e`
|
||
inline bool Contains(Enum e) const { return (set & Bit(e)) != 0; }
|
||
|
||
/// @return true if the set is empty
|
||
inline bool Empty() const { return set == 0; }
|
||
|
||
/// Equality operator
|
||
/// @param rhs the other EnumSet to compare this to
|
||
/// @return true if this EnumSet is equal to rhs
|
||
inline bool operator==(EnumSet rhs) const { return set == rhs.set; }
|
||
|
||
/// Inequality operator
|
||
/// @param rhs the other EnumSet to compare this to
|
||
/// @return true if this EnumSet is not equal to rhs
|
||
inline bool operator!=(EnumSet rhs) const { return set != rhs.set; }
|
||
|
||
/// Equality operator
|
||
/// @param rhs the enum to compare this to
|
||
/// @return true if this EnumSet only contains `rhs`
|
||
inline bool operator==(Enum rhs) const { return set == Bit(rhs); }
|
||
|
||
/// Inequality operator
|
||
/// @param rhs the enum to compare this to
|
||
/// @return false if this EnumSet only contains `rhs`
|
||
inline bool operator!=(Enum rhs) const { return set != Bit(rhs); }
|
||
|
||
/// @return the underlying value for the EnumSet
|
||
inline uint64_t Value() const { return set; }
|
||
|
||
/// Iterator provides read-only, unidirectional iterator over the enums of an
|
||
/// EnumSet.
|
||
class Iterator {
|
||
static constexpr int8_t kEnd = 63;
|
||
|
||
Iterator(uint64_t s, int8_t b) : set(s), pos(b) {}
|
||
|
||
/// Make the constructor accessible to the EnumSet.
|
||
friend struct EnumSet;
|
||
|
||
public:
|
||
/// @return the Enum value at this point in the iterator
|
||
Enum operator*() const { return static_cast<Enum>(pos); }
|
||
|
||
/// Increments the iterator
|
||
/// @returns this iterator
|
||
Iterator& operator++() {
|
||
while (pos < kEnd) {
|
||
pos++;
|
||
if (set & (static_cast<uint64_t>(1) << static_cast<uint64_t>(pos))) {
|
||
break;
|
||
}
|
||
}
|
||
return *this;
|
||
}
|
||
|
||
/// Equality operator
|
||
/// @param rhs the Iterator to compare this to
|
||
/// @return true if the two iterators are equal
|
||
bool operator==(const Iterator& rhs) const {
|
||
return set == rhs.set && pos == rhs.pos;
|
||
}
|
||
|
||
/// Inequality operator
|
||
/// @param rhs the Iterator to compare this to
|
||
/// @return true if the two iterators are different
|
||
bool operator!=(const Iterator& rhs) const { return !(*this == rhs); }
|
||
|
||
private:
|
||
const uint64_t set;
|
||
int8_t pos;
|
||
};
|
||
|
||
/// @returns an read-only iterator to the beginning of the set
|
||
Iterator begin() {
|
||
auto it = Iterator{set, -1};
|
||
++it; // Move to first set bit
|
||
return it;
|
||
}
|
||
|
||
/// @returns an iterator to the beginning of the set
|
||
Iterator end() { return Iterator{set, Iterator::kEnd}; }
|
||
|
||
private:
|
||
static constexpr uint64_t Bit(Enum value) {
|
||
return static_cast<uint64_t>(1) << static_cast<uint64_t>(value);
|
||
}
|
||
|
||
static constexpr uint64_t Union() { return 0; }
|
||
|
||
template <typename FIRST, typename... VALUES>
|
||
static constexpr uint64_t Union(FIRST first, VALUES... values) {
|
||
return Bit(first) | Union(values...);
|
||
}
|
||
|
||
uint64_t set = 0;
|
||
};
|
||
|
||
/// Writes the EnumSet to the std::ostream.
|
||
/// @param out the std::ostream to write to
|
||
/// @param set the EnumSet to write
|
||
/// @returns out so calls can be chained
|
||
template <typename ENUM>
|
||
inline std::ostream& operator<<(std::ostream& out, EnumSet<ENUM> set) {
|
||
out << "{";
|
||
bool first = true;
|
||
for (auto e : set) {
|
||
if (!first) {
|
||
out << ", ";
|
||
}
|
||
first = false;
|
||
out << e;
|
||
}
|
||
return out << "}";
|
||
}
|
||
|
||
} // namespace tint::utils
|
||
|
||
namespace std {
|
||
|
||
/// Custom std::hash specialization for tint::utils::EnumSet<T>
|
||
template <typename T>
|
||
class hash<tint::utils::EnumSet<T>> {
|
||
public:
|
||
/// @param e the EnumSet to create a hash for
|
||
/// @return the hash value
|
||
inline std::size_t operator()(const tint::utils::EnumSet<T>& e) const {
|
||
return std::hash<uint64_t>()(e.Value());
|
||
}
|
||
};
|
||
|
||
} // namespace std
|
||
|
||
#endif // SRC_TINT_UTILS_ENUM_SET_H_
|