Add ityp::vector class and unittests
In order to remove the kMaxBindingsPerGroup limit in Dawn, some static ityp::arrays need to be made dynamically sized. This CL adds ityp::vector wrapping std::vector. This CL also fixes the assumption that ityp::stack_vec iterators are pointers Bug: dawn:442, dawn:443 Change-Id: I8698cbba3ea80ac063ab918a77f223c527720d08 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/24480 Commit-Queue: Austin Eng <enga@chromium.org> Reviewed-by: Stephen White <senorblanco@chromium.org>
This commit is contained in:
parent
8e316f1177
commit
e700a6a764
|
@ -179,6 +179,7 @@ if (is_win || is_linux || is_mac || is_fuchsia || is_android) {
|
|||
"ityp_bitset.h",
|
||||
"ityp_span.h",
|
||||
"ityp_stack_vec.h",
|
||||
"ityp_vector.h",
|
||||
"vulkan_platform.h",
|
||||
"windows_with_undefs.h",
|
||||
"xlib_with_undefs.h",
|
||||
|
|
|
@ -50,6 +50,7 @@ target_sources(dawn_common PRIVATE
|
|||
"ityp_bitset.h"
|
||||
"ityp_span.h"
|
||||
"ityp_stack_vec.h"
|
||||
"ityp_vector.h"
|
||||
"vulkan_platform.h"
|
||||
"windows_with_undefs.h"
|
||||
"xlib_with_undefs.h"
|
||||
|
|
|
@ -21,10 +21,11 @@
|
|||
|
||||
namespace ityp {
|
||||
|
||||
template <typename Index, typename Value, size_t StaticCapacity = 0>
|
||||
template <typename Index, typename Value, size_t StaticCapacity>
|
||||
class stack_vec : private StackVector<Value, StaticCapacity> {
|
||||
using I = UnderlyingType<Index>;
|
||||
using Base = StackVector<Value, StaticCapacity>;
|
||||
using VectorBase = std::vector<Value, StackAllocator<Value, StaticCapacity>>;
|
||||
static_assert(StaticCapacity <= std::numeric_limits<I>::max(), "");
|
||||
|
||||
public:
|
||||
|
@ -60,35 +61,35 @@ namespace ityp {
|
|||
return this->container().data();
|
||||
}
|
||||
|
||||
Value* begin() noexcept {
|
||||
typename VectorBase::iterator begin() noexcept {
|
||||
return this->container().begin();
|
||||
}
|
||||
|
||||
const Value* begin() const noexcept {
|
||||
typename VectorBase::const_iterator begin() const noexcept {
|
||||
return this->container().begin();
|
||||
}
|
||||
|
||||
Value* end() noexcept {
|
||||
typename VectorBase::iterator end() noexcept {
|
||||
return this->container().end();
|
||||
}
|
||||
|
||||
const Value* end() const noexcept {
|
||||
typename VectorBase::const_iterator end() const noexcept {
|
||||
return this->container().end();
|
||||
}
|
||||
|
||||
Value& front() {
|
||||
typename VectorBase::reference front() {
|
||||
return this->container().front();
|
||||
}
|
||||
|
||||
const Value& front() const {
|
||||
typename VectorBase::const_reference front() const {
|
||||
return this->container().front();
|
||||
}
|
||||
|
||||
Value& back() {
|
||||
typename VectorBase::reference back() {
|
||||
return this->container().back();
|
||||
}
|
||||
|
||||
const Value& back() const {
|
||||
typename VectorBase::const_reference back() const {
|
||||
return this->container().back();
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,108 @@
|
|||
// Copyright 2020 The Dawn 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 COMMON_ITYP_VECTOR_H_
|
||||
#define COMMON_ITYP_VECTOR_H_
|
||||
|
||||
#include "common/TypedInteger.h"
|
||||
#include "common/UnderlyingType.h"
|
||||
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
namespace ityp {
|
||||
|
||||
// ityp::vector is a helper class that wraps std::vector with the restriction that
|
||||
// indices must be a particular type |Index|.
|
||||
template <typename Index, typename Value>
|
||||
class vector : public std::vector<Value> {
|
||||
using I = UnderlyingType<Index>;
|
||||
using Base = std::vector<Value>;
|
||||
|
||||
private:
|
||||
// Disallow access to base constructors and untyped index/size-related operators.
|
||||
using Base::Base;
|
||||
using Base::operator=;
|
||||
using Base::operator[];
|
||||
using Base::at;
|
||||
using Base::reserve;
|
||||
using Base::resize;
|
||||
using Base::size;
|
||||
|
||||
public:
|
||||
vector() : Base() {
|
||||
}
|
||||
|
||||
explicit vector(Index size) : Base(static_cast<I>(size)) {
|
||||
}
|
||||
|
||||
vector(Index size, const Value& init) : Base(static_cast<I>(size), init) {
|
||||
}
|
||||
|
||||
vector(const vector& rhs) : Base(static_cast<const Base&>(rhs)) {
|
||||
}
|
||||
|
||||
vector(vector&& rhs) : Base(static_cast<Base&&>(rhs)) {
|
||||
}
|
||||
|
||||
vector(std::initializer_list<Value> init) : Base(init) {
|
||||
}
|
||||
|
||||
vector& operator=(const vector& rhs) {
|
||||
Base::operator=(static_cast<const Base&>(rhs));
|
||||
return *this;
|
||||
}
|
||||
|
||||
vector& operator=(vector&& rhs) noexcept {
|
||||
Base::operator=(static_cast<Base&&>(rhs));
|
||||
return *this;
|
||||
}
|
||||
|
||||
Value& operator[](Index i) {
|
||||
ASSERT(i >= Index(0) && i < size());
|
||||
return Base::operator[](static_cast<I>(i));
|
||||
}
|
||||
|
||||
constexpr const Value& operator[](Index i) const {
|
||||
ASSERT(i >= Index(0) && i < size());
|
||||
return Base::operator[](static_cast<I>(i));
|
||||
}
|
||||
|
||||
Value& at(Index i) {
|
||||
ASSERT(i >= Index(0) && i < size());
|
||||
return Base::at(static_cast<I>(i));
|
||||
}
|
||||
|
||||
constexpr const Value& at(Index i) const {
|
||||
ASSERT(i >= Index(0) && i < size());
|
||||
return Base::at(static_cast<I>(i));
|
||||
}
|
||||
|
||||
constexpr Index size() const {
|
||||
ASSERT(std::numeric_limits<I>::max() >= Base::size());
|
||||
return Index(static_cast<I>(Base::size()));
|
||||
}
|
||||
|
||||
void resize(Index size) {
|
||||
Base::resize(static_cast<I>(size));
|
||||
}
|
||||
|
||||
void reserve(Index size) {
|
||||
Base::reserve(static_cast<I>(size));
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace ityp
|
||||
|
||||
#endif // COMMON_ITYP_VECTOR_H_
|
|
@ -162,6 +162,7 @@ test("dawn_unittests") {
|
|||
"unittests/ITypArrayTests.cpp",
|
||||
"unittests/ITypBitsetTests.cpp",
|
||||
"unittests/ITypSpanTests.cpp",
|
||||
"unittests/ITypVectorTests.cpp",
|
||||
"unittests/LinkedListTests.cpp",
|
||||
"unittests/MathTests.cpp",
|
||||
"unittests/ObjectBaseTests.cpp",
|
||||
|
|
|
@ -0,0 +1,184 @@
|
|||
// Copyright 2020 The Dawn 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 WvecANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "common/TypedInteger.h"
|
||||
#include "common/ityp_vector.h"
|
||||
|
||||
class ITypVectorTest : public testing::Test {
|
||||
protected:
|
||||
using Key = TypedInteger<struct KeyT, uint32_t>;
|
||||
using Val = TypedInteger<struct ValT, uint32_t>;
|
||||
|
||||
using Vector = ityp::vector<Key, Val>;
|
||||
};
|
||||
|
||||
// Test creation and initialization of the vector.
|
||||
TEST_F(ITypVectorTest, Creation) {
|
||||
// Default constructor initializes to 0
|
||||
{
|
||||
Vector vec;
|
||||
ASSERT_EQ(vec.size(), Key(0));
|
||||
}
|
||||
|
||||
// Size constructor initializes contents to 0
|
||||
{
|
||||
Vector vec(Key(10));
|
||||
ASSERT_EQ(vec.size(), Key(10));
|
||||
|
||||
for (Key i(0); i < Key(10); ++i) {
|
||||
ASSERT_EQ(vec[i], Val(0));
|
||||
}
|
||||
}
|
||||
|
||||
// Size and initial value constructor initializes contents to the inital value
|
||||
{
|
||||
Vector vec(Key(10), Val(7));
|
||||
ASSERT_EQ(vec.size(), Key(10));
|
||||
|
||||
for (Key i(0); i < Key(10); ++i) {
|
||||
ASSERT_EQ(vec[i], Val(7));
|
||||
}
|
||||
}
|
||||
|
||||
// Initializer list constructor
|
||||
{
|
||||
Vector vec = {Val(2), Val(8), Val(1)};
|
||||
ASSERT_EQ(vec.size(), Key(3));
|
||||
ASSERT_EQ(vec[Key(0)], Val(2));
|
||||
ASSERT_EQ(vec[Key(1)], Val(8));
|
||||
ASSERT_EQ(vec[Key(2)], Val(1));
|
||||
}
|
||||
}
|
||||
|
||||
// Test copy construction/assignment
|
||||
TEST_F(ITypVectorTest, CopyConstructAssign) {
|
||||
// Test the copy constructor
|
||||
{
|
||||
Vector rhs = {Val(2), Val(8), Val(1)};
|
||||
|
||||
Vector vec(rhs);
|
||||
ASSERT_EQ(vec.size(), Key(3));
|
||||
ASSERT_EQ(vec[Key(0)], Val(2));
|
||||
ASSERT_EQ(vec[Key(1)], Val(8));
|
||||
ASSERT_EQ(vec[Key(2)], Val(1));
|
||||
|
||||
ASSERT_EQ(rhs.size(), Key(3));
|
||||
ASSERT_EQ(rhs[Key(0)], Val(2));
|
||||
ASSERT_EQ(rhs[Key(1)], Val(8));
|
||||
ASSERT_EQ(rhs[Key(2)], Val(1));
|
||||
}
|
||||
|
||||
// Test the copy assignment
|
||||
{
|
||||
Vector rhs = {Val(2), Val(8), Val(1)};
|
||||
|
||||
Vector vec = rhs;
|
||||
ASSERT_EQ(vec.size(), Key(3));
|
||||
ASSERT_EQ(vec[Key(0)], Val(2));
|
||||
ASSERT_EQ(vec[Key(1)], Val(8));
|
||||
ASSERT_EQ(vec[Key(2)], Val(1));
|
||||
|
||||
ASSERT_EQ(rhs.size(), Key(3));
|
||||
ASSERT_EQ(rhs[Key(0)], Val(2));
|
||||
ASSERT_EQ(rhs[Key(1)], Val(8));
|
||||
ASSERT_EQ(rhs[Key(2)], Val(1));
|
||||
}
|
||||
}
|
||||
|
||||
// Test move construction/assignment
|
||||
TEST_F(ITypVectorTest, MoveConstructAssign) {
|
||||
// Test the move constructor
|
||||
{
|
||||
Vector rhs = {Val(2), Val(8), Val(1)};
|
||||
|
||||
Vector vec(std::move(rhs));
|
||||
ASSERT_EQ(vec.size(), Key(3));
|
||||
ASSERT_EQ(vec[Key(0)], Val(2));
|
||||
ASSERT_EQ(vec[Key(1)], Val(8));
|
||||
ASSERT_EQ(vec[Key(2)], Val(1));
|
||||
|
||||
ASSERT_EQ(rhs.size(), Key(0));
|
||||
}
|
||||
|
||||
// Test the move assignment
|
||||
{
|
||||
Vector rhs = {Val(2), Val(8), Val(1)};
|
||||
|
||||
Vector vec = std::move(rhs);
|
||||
ASSERT_EQ(vec.size(), Key(3));
|
||||
ASSERT_EQ(vec[Key(0)], Val(2));
|
||||
ASSERT_EQ(vec[Key(1)], Val(8));
|
||||
ASSERT_EQ(vec[Key(2)], Val(1));
|
||||
|
||||
ASSERT_EQ(rhs.size(), Key(0));
|
||||
}
|
||||
}
|
||||
|
||||
// Test that values can be set at an index and retrieved from the same index.
|
||||
TEST_F(ITypVectorTest, Indexing) {
|
||||
Vector vec(Key(10));
|
||||
{
|
||||
vec[Key(2)] = Val(5);
|
||||
vec[Key(1)] = Val(9);
|
||||
vec[Key(9)] = Val(2);
|
||||
|
||||
ASSERT_EQ(vec[Key(2)], Val(5));
|
||||
ASSERT_EQ(vec[Key(1)], Val(9));
|
||||
ASSERT_EQ(vec[Key(9)], Val(2));
|
||||
}
|
||||
{
|
||||
vec.at(Key(4)) = Val(5);
|
||||
vec.at(Key(3)) = Val(8);
|
||||
vec.at(Key(1)) = Val(7);
|
||||
|
||||
ASSERT_EQ(vec.at(Key(4)), Val(5));
|
||||
ASSERT_EQ(vec.at(Key(3)), Val(8));
|
||||
ASSERT_EQ(vec.at(Key(1)), Val(7));
|
||||
}
|
||||
}
|
||||
|
||||
// Test that the vector can be iterated in order with a range-based for loop
|
||||
TEST_F(ITypVectorTest, RangeBasedIteration) {
|
||||
Vector vec(Key(10));
|
||||
|
||||
// Assign in a non-const range-based for loop
|
||||
uint32_t i = 0;
|
||||
for (Val& val : vec) {
|
||||
val = Val(i);
|
||||
}
|
||||
|
||||
// Check values in a const range-based for loop
|
||||
i = 0;
|
||||
for (Val val : static_cast<const Vector&>(vec)) {
|
||||
ASSERT_EQ(val, vec[Key(i++)]);
|
||||
}
|
||||
}
|
||||
|
||||
// Test that begin/end/front/back/data return pointers/references to the correct elements.
|
||||
TEST_F(ITypVectorTest, BeginEndFrontBackData) {
|
||||
Vector vec(Key(10));
|
||||
|
||||
// non-const versions
|
||||
ASSERT_EQ(&vec.front(), &vec[Key(0)]);
|
||||
ASSERT_EQ(&vec.back(), &vec[Key(9)]);
|
||||
ASSERT_EQ(vec.data(), &vec[Key(0)]);
|
||||
|
||||
// const versions
|
||||
const Vector& constVec = vec;
|
||||
ASSERT_EQ(&constVec.front(), &constVec[Key(0)]);
|
||||
ASSERT_EQ(&constVec.back(), &constVec[Key(9)]);
|
||||
ASSERT_EQ(constVec.data(), &constVec[Key(0)]);
|
||||
}
|
Loading…
Reference in New Issue