Refactored enum_set
- removed forgotten file enum_set.cpp - added IsEmpty and HasAnyOf - hidden unsafe functions Add(uint32_t), Contains(uint32_t) - added new tests
This commit is contained in:
Родитель
12f5509734
Коммит
1fb8c37b57
|
@ -1,65 +0,0 @@
|
|||
// Copyright (c) 2016 Google Inc.
|
||||
//
|
||||
// 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.
|
||||
|
||||
#include "enum_set.h"
|
||||
|
||||
#include "spirv/1.1/spirv.hpp"
|
||||
|
||||
namespace {
|
||||
|
||||
// Determines whether the given enum value can be represented
|
||||
// as a bit in a uint64_t mask. If so, then returns that mask bit.
|
||||
// Otherwise, returns 0.
|
||||
uint64_t AsMask(uint32_t word) {
|
||||
if (word > 63) return 0;
|
||||
return uint64_t(1) << word;
|
||||
}
|
||||
}
|
||||
|
||||
namespace libspirv {
|
||||
|
||||
template<typename EnumType>
|
||||
void EnumSet<EnumType>::Add(uint32_t word) {
|
||||
if (auto new_bits = AsMask(word)) {
|
||||
mask_ |= new_bits;
|
||||
} else {
|
||||
Overflow().insert(word);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename EnumType>
|
||||
bool EnumSet<EnumType>::Contains(uint32_t word) const {
|
||||
// We shouldn't call Overflow() since this is a const method.
|
||||
if (auto bits = AsMask(word)) {
|
||||
return mask_ & bits;
|
||||
} else if (auto overflow = overflow_.get()) {
|
||||
return overflow->find(word) != overflow->end();
|
||||
}
|
||||
// The word is large, but the set doesn't have large members, so
|
||||
// it doesn't have an overflow set.
|
||||
return false;
|
||||
}
|
||||
|
||||
// Applies f to each capability in the set, in order from smallest enum
|
||||
// value to largest.
|
||||
void CapabilitySet::ForEach(std::function<void(SpvCapability)> f) const {
|
||||
for (uint32_t i = 0; i < 64; ++i) {
|
||||
if (mask_ & AsMask(i)) f(static_cast<SpvCapability>(i));
|
||||
}
|
||||
if (overflow_) {
|
||||
for (uint32_t c : *overflow_) f(static_cast<SpvCapability>(c));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace libspirv
|
|
@ -39,7 +39,7 @@ class EnumSet {
|
|||
|
||||
public:
|
||||
// Construct an empty set.
|
||||
EnumSet() = default;
|
||||
EnumSet() {}
|
||||
// Construct an set with just the given enum value.
|
||||
explicit EnumSet(EnumType c) { Add(c); }
|
||||
// Construct an set from an initializer list of enum values.
|
||||
|
@ -67,31 +67,10 @@ class EnumSet {
|
|||
|
||||
// Adds the given enum value to the set. This has no effect if the
|
||||
// enum value is already in the set.
|
||||
void Add(EnumType c) { Add(ToWord(c)); }
|
||||
// Adds the given enum value (as a 32-bit word) to the set. This has no
|
||||
// effect if the enum value is already in the set.
|
||||
void Add(uint32_t word) {
|
||||
if (auto new_bits = AsMask(word)) {
|
||||
mask_ |= new_bits;
|
||||
} else {
|
||||
Overflow().insert(word);
|
||||
}
|
||||
}
|
||||
void Add(EnumType c) { AddWord(ToWord(c)); }
|
||||
|
||||
// Returns true if this enum value is in the set.
|
||||
bool Contains(EnumType c) const { return Contains(ToWord(c)); }
|
||||
// Returns true if the enum represented as a 32-bit word is in the set.
|
||||
bool Contains(uint32_t word) const {
|
||||
// We shouldn't call Overflow() since this is a const method.
|
||||
if (auto bits = AsMask(word)) {
|
||||
return (mask_ & bits) != 0;
|
||||
} else if (auto overflow = overflow_.get()) {
|
||||
return overflow->find(word) != overflow->end();
|
||||
}
|
||||
// The word is large, but the set doesn't have large members, so
|
||||
// it doesn't have an overflow set.
|
||||
return false;
|
||||
}
|
||||
bool Contains(EnumType c) const { return ContainsWord(ToWord(c)); }
|
||||
|
||||
// Applies f to each enum in the set, in order from smallest enum
|
||||
// value to largest.
|
||||
|
@ -104,7 +83,56 @@ class EnumSet {
|
|||
}
|
||||
}
|
||||
|
||||
// Returns true if the set is empty.
|
||||
bool IsEmpty() const {
|
||||
if (mask_) return false;
|
||||
if (overflow_ && !overflow_->empty()) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Returns true if the set contains ANY of the elements of |in_set|,
|
||||
// or if |in_set| is empty.
|
||||
bool HasAnyOf(const EnumSet<EnumType>& in_set) const {
|
||||
if (in_set.IsEmpty()) return true;
|
||||
|
||||
if (mask_ & in_set.mask_)
|
||||
return true;
|
||||
|
||||
if (!overflow_ || !in_set.overflow_)
|
||||
return false;
|
||||
|
||||
for (uint32_t item : *in_set.overflow_) {
|
||||
if (overflow_->find(item) != overflow_->end())
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
// Adds the given enum value (as a 32-bit word) to the set. This has no
|
||||
// effect if the enum value is already in the set.
|
||||
void AddWord(uint32_t word) {
|
||||
if (auto new_bits = AsMask(word)) {
|
||||
mask_ |= new_bits;
|
||||
} else {
|
||||
Overflow().insert(word);
|
||||
}
|
||||
}
|
||||
|
||||
// Returns true if the enum represented as a 32-bit word is in the set.
|
||||
bool ContainsWord(uint32_t word) const {
|
||||
// We shouldn't call Overflow() since this is a const method.
|
||||
if (auto bits = AsMask(word)) {
|
||||
return (mask_ & bits) != 0;
|
||||
} else if (auto overflow = overflow_.get()) {
|
||||
return overflow->find(word) != overflow->end();
|
||||
}
|
||||
// The word is large, but the set doesn't have large members, so
|
||||
// it doesn't have an overflow set.
|
||||
return false;
|
||||
}
|
||||
|
||||
// Returns the enum value as a uint32_t.
|
||||
uint32_t ToWord(EnumType value) const {
|
||||
static_assert(sizeof(EnumType) <= sizeof(uint32_t),
|
||||
|
|
|
@ -74,8 +74,8 @@ set(TEST_SOURCES
|
|||
binary_strnlen_s_test.cpp
|
||||
binary_to_text_test.cpp
|
||||
binary_to_text.literal_test.cpp
|
||||
capability_set_test.cpp
|
||||
comment_test.cpp
|
||||
enum_set_test.cpp
|
||||
ext_inst.glsl_test.cpp
|
||||
ext_inst.opencl_test.cpp
|
||||
fix_word_test.cpp
|
||||
|
|
|
@ -20,16 +20,160 @@
|
|||
|
||||
namespace {
|
||||
|
||||
using libspirv::EnumSet;
|
||||
using libspirv::CapabilitySet;
|
||||
using spvtest::ElementsIn;
|
||||
using ::testing::Eq;
|
||||
using ::testing::ValuesIn;
|
||||
|
||||
TEST(CapabilitySet, DefaultIsEmpty) {
|
||||
CapabilitySet c;
|
||||
TEST(EnumSet, IsEmpty1) {
|
||||
EnumSet<uint32_t> set;
|
||||
EXPECT_TRUE(set.IsEmpty());
|
||||
set.Add(0);
|
||||
EXPECT_FALSE(set.IsEmpty());
|
||||
}
|
||||
|
||||
TEST(EnumSet, IsEmpty2) {
|
||||
EnumSet<uint32_t> set;
|
||||
EXPECT_TRUE(set.IsEmpty());
|
||||
set.Add(150);
|
||||
EXPECT_FALSE(set.IsEmpty());
|
||||
}
|
||||
|
||||
TEST(EnumSet, IsEmpty3) {
|
||||
EnumSet<uint32_t> set(4);
|
||||
EXPECT_FALSE(set.IsEmpty());
|
||||
}
|
||||
|
||||
TEST(EnumSet, IsEmpty4) {
|
||||
EnumSet<uint32_t> set(300);
|
||||
EXPECT_FALSE(set.IsEmpty());
|
||||
}
|
||||
|
||||
TEST(EnumSetHasAnyOf, EmptySetEmptyQuery) {
|
||||
const EnumSet<uint32_t> set;
|
||||
const EnumSet<uint32_t> empty;
|
||||
EXPECT_TRUE(set.HasAnyOf(empty));
|
||||
EXPECT_TRUE(EnumSet<uint32_t>().HasAnyOf(EnumSet<uint32_t>()));
|
||||
}
|
||||
|
||||
TEST(EnumSetHasAnyOf, MaskSetEmptyQuery) {
|
||||
EnumSet<uint32_t> set;
|
||||
const EnumSet<uint32_t> empty;
|
||||
set.Add(5);
|
||||
set.Add(8);
|
||||
EXPECT_TRUE(set.HasAnyOf(empty));
|
||||
}
|
||||
|
||||
TEST(EnumSetHasAnyOf, OverflowSetEmptyQuery) {
|
||||
EnumSet<uint32_t> set;
|
||||
const EnumSet<uint32_t> empty;
|
||||
set.Add(200);
|
||||
set.Add(300);
|
||||
EXPECT_TRUE(set.HasAnyOf(empty));
|
||||
}
|
||||
|
||||
TEST(EnumSetHasAnyOf, EmptyQuery) {
|
||||
EnumSet<uint32_t> set;
|
||||
const EnumSet<uint32_t> empty;
|
||||
set.Add(5);
|
||||
set.Add(8);
|
||||
set.Add(200);
|
||||
set.Add(300);
|
||||
EXPECT_TRUE(set.HasAnyOf(empty));
|
||||
}
|
||||
|
||||
TEST(EnumSetHasAnyOf, EmptyQueryAlwaysTrue) {
|
||||
EnumSet<uint32_t> set;
|
||||
const EnumSet<uint32_t> empty;
|
||||
EXPECT_TRUE(set.HasAnyOf(empty));
|
||||
set.Add(5);
|
||||
EXPECT_TRUE(set.HasAnyOf(empty));
|
||||
|
||||
EXPECT_TRUE(EnumSet<uint32_t>(100).HasAnyOf(EnumSet<uint32_t>()));
|
||||
}
|
||||
|
||||
TEST(EnumSetHasAnyOf, ReflexiveMask) {
|
||||
EnumSet<uint32_t> set(3);
|
||||
set.Add(24);
|
||||
set.Add(30);
|
||||
EXPECT_TRUE(set.HasAnyOf(set));
|
||||
}
|
||||
|
||||
TEST(EnumSetHasAnyOf, ReflexiveOverflow) {
|
||||
EnumSet<uint32_t> set(200);
|
||||
set.Add(300);
|
||||
set.Add(400);
|
||||
EXPECT_TRUE(set.HasAnyOf(set));
|
||||
}
|
||||
|
||||
TEST(EnumSetHasAnyOf, Reflexive) {
|
||||
EnumSet<uint32_t> set(3);
|
||||
set.Add(24);
|
||||
set.Add(300);
|
||||
set.Add(400);
|
||||
EXPECT_TRUE(set.HasAnyOf(set));
|
||||
}
|
||||
|
||||
TEST(EnumSetHasAnyOf, EmptySetHasNone) {
|
||||
EnumSet<uint32_t> set;
|
||||
EnumSet<uint32_t> items;
|
||||
for (uint32_t i = 0; i < 200; ++i) {
|
||||
items.Add(i);
|
||||
EXPECT_FALSE(set.HasAnyOf(items));
|
||||
EXPECT_FALSE(set.HasAnyOf(EnumSet<uint32_t>(i)));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(EnumSetHasAnyOf, MaskSetMaskQuery) {
|
||||
EnumSet<uint32_t> set(0);
|
||||
EnumSet<uint32_t> items(1);
|
||||
EXPECT_FALSE(set.HasAnyOf(items));
|
||||
set.Add(2);
|
||||
items.Add(3);
|
||||
EXPECT_FALSE(set.HasAnyOf(items));
|
||||
set.Add(3);
|
||||
EXPECT_TRUE(set.HasAnyOf(items));
|
||||
set.Add(4);
|
||||
EXPECT_TRUE(set.HasAnyOf(items));
|
||||
}
|
||||
|
||||
TEST(EnumSetHasAnyOf, OverflowSetOverflowQuery) {
|
||||
EnumSet<uint32_t> set(100);
|
||||
EnumSet<uint32_t> items(200);
|
||||
EXPECT_FALSE(set.HasAnyOf(items));
|
||||
set.Add(300);
|
||||
items.Add(400);
|
||||
EXPECT_FALSE(set.HasAnyOf(items));
|
||||
set.Add(200);
|
||||
EXPECT_TRUE(set.HasAnyOf(items));
|
||||
set.Add(500);
|
||||
EXPECT_TRUE(set.HasAnyOf(items));
|
||||
}
|
||||
|
||||
TEST(EnumSetHasAnyOf, GeneralCase) {
|
||||
EnumSet<uint32_t> set(0);
|
||||
EnumSet<uint32_t> items(100);
|
||||
EXPECT_FALSE(set.HasAnyOf(items));
|
||||
set.Add(300);
|
||||
items.Add(4);
|
||||
EXPECT_FALSE(set.HasAnyOf(items));
|
||||
set.Add(5);
|
||||
items.Add(500);
|
||||
EXPECT_FALSE(set.HasAnyOf(items));
|
||||
set.Add(500);
|
||||
EXPECT_TRUE(set.HasAnyOf(items));
|
||||
EXPECT_FALSE(set.HasAnyOf(EnumSet<uint32_t>(20)));
|
||||
EXPECT_FALSE(set.HasAnyOf(EnumSet<uint32_t>(600)));
|
||||
EXPECT_TRUE(set.HasAnyOf(EnumSet<uint32_t>(5)));
|
||||
EXPECT_TRUE(set.HasAnyOf(EnumSet<uint32_t>(300)));
|
||||
EXPECT_TRUE(set.HasAnyOf(EnumSet<uint32_t>(0)));
|
||||
}
|
||||
|
||||
TEST(EnumSet, DefaultIsEmpty) {
|
||||
EnumSet<uint32_t> set;
|
||||
for (uint32_t i = 0; i < 1000; ++i) {
|
||||
EXPECT_FALSE(c.Contains(i));
|
||||
EXPECT_FALSE(c.Contains(static_cast<SpvCapability>(i)));
|
||||
EXPECT_FALSE(set.Contains(i));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -37,16 +181,16 @@ TEST(CapabilitySet, ConstructSingleMemberMatrix) {
|
|||
CapabilitySet s(SpvCapabilityMatrix);
|
||||
EXPECT_TRUE(s.Contains(SpvCapabilityMatrix));
|
||||
EXPECT_FALSE(s.Contains(SpvCapabilityShader));
|
||||
EXPECT_FALSE(s.Contains(1000));
|
||||
EXPECT_FALSE(s.Contains(static_cast<SpvCapability>(1000)));
|
||||
}
|
||||
|
||||
TEST(CapabilitySet, ConstructSingleMemberMaxInMask) {
|
||||
CapabilitySet s(static_cast<SpvCapability>(63));
|
||||
EXPECT_FALSE(s.Contains(SpvCapabilityMatrix));
|
||||
EXPECT_FALSE(s.Contains(SpvCapabilityShader));
|
||||
EXPECT_TRUE(s.Contains(63));
|
||||
EXPECT_FALSE(s.Contains(64));
|
||||
EXPECT_FALSE(s.Contains(1000));
|
||||
EXPECT_TRUE(s.Contains(static_cast<SpvCapability>(63)));
|
||||
EXPECT_FALSE(s.Contains(static_cast<SpvCapability>(64)));
|
||||
EXPECT_FALSE(s.Contains(static_cast<SpvCapability>(1000)));
|
||||
}
|
||||
|
||||
TEST(CapabilitySet, ConstructSingleMemberMinOverflow) {
|
||||
|
@ -54,41 +198,34 @@ TEST(CapabilitySet, ConstructSingleMemberMinOverflow) {
|
|||
CapabilitySet s(static_cast<SpvCapability>(64));
|
||||
EXPECT_FALSE(s.Contains(SpvCapabilityMatrix));
|
||||
EXPECT_FALSE(s.Contains(SpvCapabilityShader));
|
||||
EXPECT_FALSE(s.Contains(63));
|
||||
EXPECT_TRUE(s.Contains(64));
|
||||
EXPECT_FALSE(s.Contains(1000));
|
||||
EXPECT_FALSE(s.Contains(static_cast<SpvCapability>(63)));
|
||||
EXPECT_TRUE(s.Contains(static_cast<SpvCapability>(64)));
|
||||
EXPECT_FALSE(s.Contains(static_cast<SpvCapability>(1000)));
|
||||
}
|
||||
|
||||
TEST(CapabilitySet, ConstructSingleMemberMaxOverflow) {
|
||||
// Check the max 32-bit signed int.
|
||||
CapabilitySet s(SpvCapability(0x7fffffffu));
|
||||
CapabilitySet s(static_cast<SpvCapability>(0x7fffffffu));
|
||||
EXPECT_FALSE(s.Contains(SpvCapabilityMatrix));
|
||||
EXPECT_FALSE(s.Contains(SpvCapabilityShader));
|
||||
EXPECT_FALSE(s.Contains(1000));
|
||||
EXPECT_TRUE(s.Contains(0x7fffffffu));
|
||||
EXPECT_FALSE(s.Contains(static_cast<SpvCapability>(1000)));
|
||||
EXPECT_TRUE(s.Contains(static_cast<SpvCapability>(0x7fffffffu)));
|
||||
}
|
||||
|
||||
TEST(CapabilitySet, AddEnum) {
|
||||
CapabilitySet s(SpvCapabilityShader);
|
||||
s.Add(SpvCapabilityKernel);
|
||||
s.Add(static_cast<SpvCapability>(42));
|
||||
EXPECT_FALSE(s.Contains(SpvCapabilityMatrix));
|
||||
EXPECT_TRUE(s.Contains(SpvCapabilityShader));
|
||||
EXPECT_TRUE(s.Contains(SpvCapabilityKernel));
|
||||
}
|
||||
|
||||
TEST(CapabilitySet, AddInt) {
|
||||
CapabilitySet s(SpvCapabilityShader);
|
||||
s.Add(42);
|
||||
EXPECT_FALSE(s.Contains(SpvCapabilityMatrix));
|
||||
EXPECT_TRUE(s.Contains(SpvCapabilityShader));
|
||||
EXPECT_TRUE(s.Contains(42));
|
||||
EXPECT_TRUE(s.Contains(static_cast<SpvCapability>(42)));
|
||||
}
|
||||
|
||||
TEST(CapabilitySet, InitializerListEmpty) {
|
||||
CapabilitySet s{};
|
||||
for (uint32_t i = 0; i < 1000; i++) {
|
||||
EXPECT_FALSE(s.Contains(i));
|
||||
EXPECT_FALSE(s.Contains(static_cast<SpvCapability>(i)));
|
||||
}
|
||||
}
|
||||
|
Загрузка…
Ссылка в новой задаче