Consistent formatting for Dawn/Tint.
This CL updates the clang format files to have a single shared format
between Dawn and Tint. The major changes are tabs are 4 spaces, lines
are 100 columns and namespaces are not indented.
Bug: dawn:1339
Change-Id: I4208742c95643998d9fd14e77a9cc558071ded39
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/87603
Commit-Queue: Dan Sinclair <dsinclair@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Kokoro: Kokoro <noreply+kokoro@google.com>
diff --git a/src/tint/utils/block_allocator.h b/src/tint/utils/block_allocator.h
index 4823fae..0fdf66a 100644
--- a/src/tint/utils/block_allocator.h
+++ b/src/tint/utils/block_allocator.h
@@ -28,265 +28,259 @@
/// objects are automatically destructed and freed.
///
/// Objects held by the BlockAllocator can be iterated over using a View.
-template <typename T,
- size_t BLOCK_SIZE = 64 * 1024,
- size_t BLOCK_ALIGNMENT = 16>
+template <typename T, size_t BLOCK_SIZE = 64 * 1024, size_t BLOCK_ALIGNMENT = 16>
class BlockAllocator {
- /// Pointers is a chunk of T* pointers, forming a linked list.
- /// The list of Pointers are used to maintain the list of allocated objects.
- /// Pointers are allocated out of the block memory.
- struct Pointers {
- static constexpr size_t kMax = 32;
- std::array<T*, kMax> ptrs;
- Pointers* next;
- };
+ /// Pointers is a chunk of T* pointers, forming a linked list.
+ /// The list of Pointers are used to maintain the list of allocated objects.
+ /// Pointers are allocated out of the block memory.
+ struct Pointers {
+ static constexpr size_t kMax = 32;
+ std::array<T*, kMax> ptrs;
+ Pointers* next;
+ };
- /// Block is linked list of memory blocks.
- /// Blocks are allocated out of heap memory.
- ///
- /// Note: We're not using std::aligned_storage here as this warns / errors
- /// on MSVC.
- struct alignas(BLOCK_ALIGNMENT) Block {
- uint8_t data[BLOCK_SIZE];
- Block* next;
- };
+ /// Block is linked list of memory blocks.
+ /// Blocks are allocated out of heap memory.
+ ///
+ /// Note: We're not using std::aligned_storage here as this warns / errors
+ /// on MSVC.
+ struct alignas(BLOCK_ALIGNMENT) Block {
+ uint8_t data[BLOCK_SIZE];
+ Block* next;
+ };
- // Forward declaration
- template <bool IS_CONST>
- class TView;
+ // Forward declaration
+ template <bool IS_CONST>
+ class TView;
- /// An iterator for the objects owned by the BlockAllocator.
- template <bool IS_CONST>
- class TIterator {
- using PointerTy = std::conditional_t<IS_CONST, const T*, T*>;
+ /// An iterator for the objects owned by the BlockAllocator.
+ template <bool IS_CONST>
+ class TIterator {
+ using PointerTy = std::conditional_t<IS_CONST, const T*, T*>;
- public:
- /// Equality operator
- /// @param other the iterator to compare this iterator to
- /// @returns true if this iterator is equal to other
- bool operator==(const TIterator& other) const {
- return ptrs == other.ptrs && idx == other.idx;
- }
-
- /// Inequality operator
- /// @param other the iterator to compare this iterator to
- /// @returns true if this iterator is not equal to other
- bool operator!=(const TIterator& other) const { return !(*this == other); }
-
- /// Advances the iterator
- /// @returns this iterator
- TIterator& operator++() {
- if (ptrs != nullptr) {
- ++idx;
- if (idx == Pointers::kMax) {
- idx = 0;
- ptrs = ptrs->next;
+ public:
+ /// Equality operator
+ /// @param other the iterator to compare this iterator to
+ /// @returns true if this iterator is equal to other
+ bool operator==(const TIterator& other) const {
+ return ptrs == other.ptrs && idx == other.idx;
}
- }
- return *this;
+
+ /// Inequality operator
+ /// @param other the iterator to compare this iterator to
+ /// @returns true if this iterator is not equal to other
+ bool operator!=(const TIterator& other) const { return !(*this == other); }
+
+ /// Advances the iterator
+ /// @returns this iterator
+ TIterator& operator++() {
+ if (ptrs != nullptr) {
+ ++idx;
+ if (idx == Pointers::kMax) {
+ idx = 0;
+ ptrs = ptrs->next;
+ }
+ }
+ return *this;
+ }
+
+ /// @returns the pointer to the object at the current iterator position
+ PointerTy operator*() const { return ptrs ? ptrs->ptrs[idx] : nullptr; }
+
+ private:
+ friend TView<IS_CONST>; // Keep internal iterator impl private.
+ explicit TIterator(const Pointers* p, size_t i) : ptrs(p), idx(i) {}
+
+ const Pointers* ptrs;
+ size_t idx;
+ };
+
+ /// View provides begin() and end() methods for looping over the objects
+ /// owned by the BlockAllocator.
+ template <bool IS_CONST>
+ class TView {
+ public:
+ /// @returns an iterator to the beginning of the view
+ TIterator<IS_CONST> begin() const {
+ return TIterator<IS_CONST>{allocator_->pointers_.root, 0};
+ }
+
+ /// @returns an iterator to the end of the view
+ TIterator<IS_CONST> end() const {
+ return allocator_->pointers_.current_index >= Pointers::kMax
+ ? TIterator<IS_CONST>(nullptr, 0)
+ : TIterator<IS_CONST>(allocator_->pointers_.current,
+ allocator_->pointers_.current_index);
+ }
+
+ private:
+ friend BlockAllocator; // For BlockAllocator::operator View()
+ explicit TView(BlockAllocator const* allocator) : allocator_(allocator) {}
+ BlockAllocator const* const allocator_;
+ };
+
+ public:
+ /// An iterator type over the objects of the BlockAllocator
+ using Iterator = TIterator<false>;
+
+ /// An immutable iterator type over the objects of the BlockAllocator
+ using ConstIterator = TIterator<true>;
+
+ /// View provides begin() and end() methods for looping over the objects
+ /// owned by the BlockAllocator.
+ using View = TView<false>;
+
+ /// ConstView provides begin() and end() methods for looping over the objects
+ /// owned by the BlockAllocator.
+ using ConstView = TView<true>;
+
+ /// Constructor
+ BlockAllocator() = default;
+
+ /// Move constructor
+ /// @param rhs the BlockAllocator to move
+ BlockAllocator(BlockAllocator&& rhs) {
+ std::swap(block_, rhs.block_);
+ std::swap(pointers_, rhs.pointers_);
}
- /// @returns the pointer to the object at the current iterator position
- PointerTy operator*() const { return ptrs ? ptrs->ptrs[idx] : nullptr; }
-
- private:
- friend TView<IS_CONST>; // Keep internal iterator impl private.
- explicit TIterator(const Pointers* p, size_t i) : ptrs(p), idx(i) {}
-
- const Pointers* ptrs;
- size_t idx;
- };
-
- /// View provides begin() and end() methods for looping over the objects
- /// owned by the BlockAllocator.
- template <bool IS_CONST>
- class TView {
- public:
- /// @returns an iterator to the beginning of the view
- TIterator<IS_CONST> begin() const {
- return TIterator<IS_CONST>{allocator_->pointers_.root, 0};
+ /// Move assignment operator
+ /// @param rhs the BlockAllocator to move
+ /// @return this BlockAllocator
+ BlockAllocator& operator=(BlockAllocator&& rhs) {
+ if (this != &rhs) {
+ Reset();
+ std::swap(block_, rhs.block_);
+ std::swap(pointers_, rhs.pointers_);
+ }
+ return *this;
}
- /// @returns an iterator to the end of the view
- TIterator<IS_CONST> end() const {
- return allocator_->pointers_.current_index >= Pointers::kMax
- ? TIterator<IS_CONST>(nullptr, 0)
- : TIterator<IS_CONST>(allocator_->pointers_.current,
- allocator_->pointers_.current_index);
+ /// Destructor
+ ~BlockAllocator() { Reset(); }
+
+ /// @return a View of all objects owned by this BlockAllocator
+ View Objects() { return View(this); }
+
+ /// @return a ConstView of all objects owned by this BlockAllocator
+ ConstView Objects() const { return ConstView(this); }
+
+ /// Creates a new `TYPE` owned by the BlockAllocator.
+ /// When the BlockAllocator is destructed the object will be destructed and
+ /// freed.
+ /// @param args the arguments to pass to the type constructor
+ /// @returns the pointer to the constructed object
+ template <typename TYPE = T, typename... ARGS>
+ TYPE* Create(ARGS&&... args) {
+ static_assert(std::is_same<T, TYPE>::value || std::is_base_of<T, TYPE>::value,
+ "TYPE does not derive from T");
+ static_assert(std::is_same<T, TYPE>::value || std::has_virtual_destructor<T>::value,
+ "TYPE requires a virtual destructor when calling Create() for a type "
+ "that is not T");
+
+ auto* ptr = Allocate<TYPE>();
+ new (ptr) TYPE(std::forward<ARGS>(args)...);
+ AddObjectPointer(ptr);
+
+ return ptr;
}
- private:
- friend BlockAllocator; // For BlockAllocator::operator View()
- explicit TView(BlockAllocator const* allocator) : allocator_(allocator) {}
- BlockAllocator const* const allocator_;
- };
-
- public:
- /// An iterator type over the objects of the BlockAllocator
- using Iterator = TIterator<false>;
-
- /// An immutable iterator type over the objects of the BlockAllocator
- using ConstIterator = TIterator<true>;
-
- /// View provides begin() and end() methods for looping over the objects
- /// owned by the BlockAllocator.
- using View = TView<false>;
-
- /// ConstView provides begin() and end() methods for looping over the objects
- /// owned by the BlockAllocator.
- using ConstView = TView<true>;
-
- /// Constructor
- BlockAllocator() = default;
-
- /// Move constructor
- /// @param rhs the BlockAllocator to move
- BlockAllocator(BlockAllocator&& rhs) {
- std::swap(block_, rhs.block_);
- std::swap(pointers_, rhs.pointers_);
- }
-
- /// Move assignment operator
- /// @param rhs the BlockAllocator to move
- /// @return this BlockAllocator
- BlockAllocator& operator=(BlockAllocator&& rhs) {
- if (this != &rhs) {
- Reset();
- std::swap(block_, rhs.block_);
- std::swap(pointers_, rhs.pointers_);
- }
- return *this;
- }
-
- /// Destructor
- ~BlockAllocator() { Reset(); }
-
- /// @return a View of all objects owned by this BlockAllocator
- View Objects() { return View(this); }
-
- /// @return a ConstView of all objects owned by this BlockAllocator
- ConstView Objects() const { return ConstView(this); }
-
- /// Creates a new `TYPE` owned by the BlockAllocator.
- /// When the BlockAllocator is destructed the object will be destructed and
- /// freed.
- /// @param args the arguments to pass to the type constructor
- /// @returns the pointer to the constructed object
- template <typename TYPE = T, typename... ARGS>
- TYPE* Create(ARGS&&... args) {
- static_assert(
- std::is_same<T, TYPE>::value || std::is_base_of<T, TYPE>::value,
- "TYPE does not derive from T");
- static_assert(
- std::is_same<T, TYPE>::value || std::has_virtual_destructor<T>::value,
- "TYPE requires a virtual destructor when calling Create() for a type "
- "that is not T");
-
- auto* ptr = Allocate<TYPE>();
- new (ptr) TYPE(std::forward<ARGS>(args)...);
- AddObjectPointer(ptr);
-
- return ptr;
- }
-
- /// Frees all allocations from the allocator.
- void Reset() {
- for (auto ptr : Objects()) {
- ptr->~T();
- }
- auto* block = block_.root;
- while (block != nullptr) {
- auto* next = block->next;
- delete block;
- block = next;
- }
- block_ = {};
- pointers_ = {};
- }
-
- private:
- BlockAllocator(const BlockAllocator&) = delete;
- BlockAllocator& operator=(const BlockAllocator&) = delete;
-
- /// Allocates an instance of TYPE from the current block, or from a newly
- /// allocated block if the current block is full.
- template <typename TYPE>
- TYPE* Allocate() {
- static_assert(sizeof(TYPE) <= BLOCK_SIZE,
- "Cannot construct TYPE with size greater than BLOCK_SIZE");
- static_assert(alignof(TYPE) <= BLOCK_ALIGNMENT,
- "alignof(TYPE) is greater than ALIGNMENT");
-
- block_.current_offset =
- utils::RoundUp(alignof(TYPE), block_.current_offset);
- if (block_.current_offset + sizeof(TYPE) > BLOCK_SIZE) {
- // Allocate a new block from the heap
- auto* prev_block = block_.current;
- block_.current = new Block;
- if (!block_.current) {
- return nullptr; // out of memory
- }
- block_.current->next = nullptr;
- block_.current_offset = 0;
- if (prev_block) {
- prev_block->next = block_.current;
- } else {
- block_.root = block_.current;
- }
+ /// Frees all allocations from the allocator.
+ void Reset() {
+ for (auto ptr : Objects()) {
+ ptr->~T();
+ }
+ auto* block = block_.root;
+ while (block != nullptr) {
+ auto* next = block->next;
+ delete block;
+ block = next;
+ }
+ block_ = {};
+ pointers_ = {};
}
- auto* base = &block_.current->data[0];
- auto* ptr = reinterpret_cast<TYPE*>(base + block_.current_offset);
- block_.current_offset += sizeof(TYPE);
- return ptr;
- }
+ private:
+ BlockAllocator(const BlockAllocator&) = delete;
+ BlockAllocator& operator=(const BlockAllocator&) = delete;
- /// Adds `ptr` to the linked list of objects owned by this BlockAllocator.
- /// Once added, `ptr` will be tracked for destruction when the BlockAllocator
- /// is destructed.
- void AddObjectPointer(T* ptr) {
- if (pointers_.current_index >= Pointers::kMax) {
- auto* prev_pointers = pointers_.current;
- pointers_.current = Allocate<Pointers>();
- if (!pointers_.current) {
- return; // out of memory
- }
- pointers_.current->next = nullptr;
- pointers_.current_index = 0;
+ /// Allocates an instance of TYPE from the current block, or from a newly
+ /// allocated block if the current block is full.
+ template <typename TYPE>
+ TYPE* Allocate() {
+ static_assert(sizeof(TYPE) <= BLOCK_SIZE,
+ "Cannot construct TYPE with size greater than BLOCK_SIZE");
+ static_assert(alignof(TYPE) <= BLOCK_ALIGNMENT, "alignof(TYPE) is greater than ALIGNMENT");
- if (prev_pointers) {
- prev_pointers->next = pointers_.current;
- } else {
- pointers_.root = pointers_.current;
- }
+ block_.current_offset = utils::RoundUp(alignof(TYPE), block_.current_offset);
+ if (block_.current_offset + sizeof(TYPE) > BLOCK_SIZE) {
+ // Allocate a new block from the heap
+ auto* prev_block = block_.current;
+ block_.current = new Block;
+ if (!block_.current) {
+ return nullptr; // out of memory
+ }
+ block_.current->next = nullptr;
+ block_.current_offset = 0;
+ if (prev_block) {
+ prev_block->next = block_.current;
+ } else {
+ block_.root = block_.current;
+ }
+ }
+
+ auto* base = &block_.current->data[0];
+ auto* ptr = reinterpret_cast<TYPE*>(base + block_.current_offset);
+ block_.current_offset += sizeof(TYPE);
+ return ptr;
}
- pointers_.current->ptrs[pointers_.current_index++] = ptr;
- }
+ /// Adds `ptr` to the linked list of objects owned by this BlockAllocator.
+ /// Once added, `ptr` will be tracked for destruction when the BlockAllocator
+ /// is destructed.
+ void AddObjectPointer(T* ptr) {
+ if (pointers_.current_index >= Pointers::kMax) {
+ auto* prev_pointers = pointers_.current;
+ pointers_.current = Allocate<Pointers>();
+ if (!pointers_.current) {
+ return; // out of memory
+ }
+ pointers_.current->next = nullptr;
+ pointers_.current_index = 0;
- struct {
- /// The root block of the block linked list
- Block* root = nullptr;
- /// The current (end) block of the blocked linked list.
- /// New allocations come from this block
- Block* current = nullptr;
- /// The byte offset in #current for the next allocation.
- /// Initialized with BLOCK_SIZE so that the first allocation triggers a
- /// block allocation.
- size_t current_offset = BLOCK_SIZE;
- } block_;
+ if (prev_pointers) {
+ prev_pointers->next = pointers_.current;
+ } else {
+ pointers_.root = pointers_.current;
+ }
+ }
- struct {
- /// The root Pointers structure of the pointers linked list
- Pointers* root = nullptr;
- /// The current (end) Pointers structure of the pointers linked list.
- /// AddObjectPointer() adds to this structure.
- Pointers* current = nullptr;
- /// The array index in #current for the next append.
- /// Initialized with Pointers::kMax so that the first append triggers a
- /// allocation of the Pointers structure.
- size_t current_index = Pointers::kMax;
- } pointers_;
+ pointers_.current->ptrs[pointers_.current_index++] = ptr;
+ }
+
+ struct {
+ /// The root block of the block linked list
+ Block* root = nullptr;
+ /// The current (end) block of the blocked linked list.
+ /// New allocations come from this block
+ Block* current = nullptr;
+ /// The byte offset in #current for the next allocation.
+ /// Initialized with BLOCK_SIZE so that the first allocation triggers a
+ /// block allocation.
+ size_t current_offset = BLOCK_SIZE;
+ } block_;
+
+ struct {
+ /// The root Pointers structure of the pointers linked list
+ Pointers* root = nullptr;
+ /// The current (end) Pointers structure of the pointers linked list.
+ /// AddObjectPointer() adds to this structure.
+ Pointers* current = nullptr;
+ /// The array index in #current for the next append.
+ /// Initialized with Pointers::kMax so that the first append triggers a
+ /// allocation of the Pointers structure.
+ size_t current_index = Pointers::kMax;
+ } pointers_;
};
} // namespace tint::utils
diff --git a/src/tint/utils/block_allocator_test.cc b/src/tint/utils/block_allocator_test.cc
index ace0e9f..600019c 100644
--- a/src/tint/utils/block_allocator_test.cc
+++ b/src/tint/utils/block_allocator_test.cc
@@ -20,127 +20,125 @@
namespace {
struct LifetimeCounter {
- explicit LifetimeCounter(size_t* count) : count_(count) { (*count)++; }
- ~LifetimeCounter() { (*count_)--; }
+ explicit LifetimeCounter(size_t* count) : count_(count) { (*count)++; }
+ ~LifetimeCounter() { (*count_)--; }
- size_t* const count_;
+ size_t* const count_;
};
using BlockAllocatorTest = testing::Test;
TEST_F(BlockAllocatorTest, Empty) {
- using Allocator = BlockAllocator<int>;
+ using Allocator = BlockAllocator<int>;
- Allocator allocator;
+ Allocator allocator;
- for (int* i : allocator.Objects()) {
- (void)i;
- if ((true)) { // Workaround for "error: loop will run at most once"
- FAIL() << "BlockAllocator should be empty";
+ for (int* i : allocator.Objects()) {
+ (void)i;
+ if ((true)) { // Workaround for "error: loop will run at most once"
+ FAIL() << "BlockAllocator should be empty";
+ }
}
- }
- for (const int* i : static_cast<const Allocator&>(allocator).Objects()) {
- (void)i;
- if ((true)) { // Workaround for "error: loop will run at most once"
- FAIL() << "BlockAllocator should be empty";
+ for (const int* i : static_cast<const Allocator&>(allocator).Objects()) {
+ (void)i;
+ if ((true)) { // Workaround for "error: loop will run at most once"
+ FAIL() << "BlockAllocator should be empty";
+ }
}
- }
}
TEST_F(BlockAllocatorTest, ObjectLifetime) {
- using Allocator = BlockAllocator<LifetimeCounter>;
+ using Allocator = BlockAllocator<LifetimeCounter>;
- size_t count = 0;
- {
- Allocator allocator;
+ size_t count = 0;
+ {
+ Allocator allocator;
+ EXPECT_EQ(count, 0u);
+ allocator.Create(&count);
+ EXPECT_EQ(count, 1u);
+ allocator.Create(&count);
+ EXPECT_EQ(count, 2u);
+ allocator.Create(&count);
+ EXPECT_EQ(count, 3u);
+ }
EXPECT_EQ(count, 0u);
- allocator.Create(&count);
- EXPECT_EQ(count, 1u);
- allocator.Create(&count);
- EXPECT_EQ(count, 2u);
- allocator.Create(&count);
- EXPECT_EQ(count, 3u);
- }
- EXPECT_EQ(count, 0u);
}
TEST_F(BlockAllocatorTest, MoveConstruct) {
- using Allocator = BlockAllocator<LifetimeCounter>;
+ using Allocator = BlockAllocator<LifetimeCounter>;
- for (size_t n :
- {0, 1, 10, 16, 20, 32, 50, 64, 100, 256, 300, 512, 500, 512}) {
- size_t count = 0;
- {
- Allocator allocator_a;
- for (size_t i = 0; i < n; i++) {
- allocator_a.Create(&count);
- }
- EXPECT_EQ(count, n);
+ for (size_t n : {0, 1, 10, 16, 20, 32, 50, 64, 100, 256, 300, 512, 500, 512}) {
+ size_t count = 0;
+ {
+ Allocator allocator_a;
+ for (size_t i = 0; i < n; i++) {
+ allocator_a.Create(&count);
+ }
+ EXPECT_EQ(count, n);
- Allocator allocator_b{std::move(allocator_a)};
- EXPECT_EQ(count, n);
+ Allocator allocator_b{std::move(allocator_a)};
+ EXPECT_EQ(count, n);
+ }
+
+ EXPECT_EQ(count, 0u);
}
-
- EXPECT_EQ(count, 0u);
- }
}
TEST_F(BlockAllocatorTest, MoveAssign) {
- using Allocator = BlockAllocator<LifetimeCounter>;
+ using Allocator = BlockAllocator<LifetimeCounter>;
- for (size_t n :
- {0, 1, 10, 16, 20, 32, 50, 64, 100, 256, 300, 512, 500, 512}) {
- size_t count_a = 0;
- size_t count_b = 0;
+ for (size_t n : {0, 1, 10, 16, 20, 32, 50, 64, 100, 256, 300, 512, 500, 512}) {
+ size_t count_a = 0;
+ size_t count_b = 0;
- {
- Allocator allocator_a;
- for (size_t i = 0; i < n; i++) {
- allocator_a.Create(&count_a);
- }
- EXPECT_EQ(count_a, n);
+ {
+ Allocator allocator_a;
+ for (size_t i = 0; i < n; i++) {
+ allocator_a.Create(&count_a);
+ }
+ EXPECT_EQ(count_a, n);
- Allocator allocator_b;
- for (size_t i = 0; i < n; i++) {
- allocator_b.Create(&count_b);
- }
- EXPECT_EQ(count_b, n);
+ Allocator allocator_b;
+ for (size_t i = 0; i < n; i++) {
+ allocator_b.Create(&count_b);
+ }
+ EXPECT_EQ(count_b, n);
- allocator_b = std::move(allocator_a);
- EXPECT_EQ(count_a, n);
- EXPECT_EQ(count_b, 0u);
+ allocator_b = std::move(allocator_a);
+ EXPECT_EQ(count_a, n);
+ EXPECT_EQ(count_b, 0u);
+ }
+
+ EXPECT_EQ(count_a, 0u);
+ EXPECT_EQ(count_b, 0u);
}
-
- EXPECT_EQ(count_a, 0u);
- EXPECT_EQ(count_b, 0u);
- }
}
TEST_F(BlockAllocatorTest, ObjectOrder) {
- using Allocator = BlockAllocator<int>;
+ using Allocator = BlockAllocator<int>;
- Allocator allocator;
- constexpr int N = 10000;
- for (int i = 0; i < N; i++) {
- allocator.Create(i);
- }
+ Allocator allocator;
+ constexpr int N = 10000;
+ for (int i = 0; i < N; i++) {
+ allocator.Create(i);
+ }
- {
- int i = 0;
- for (int* p : allocator.Objects()) {
- EXPECT_EQ(*p, i);
- i++;
+ {
+ int i = 0;
+ for (int* p : allocator.Objects()) {
+ EXPECT_EQ(*p, i);
+ i++;
+ }
+ EXPECT_EQ(i, N);
}
- EXPECT_EQ(i, N);
- }
- {
- int i = 0;
- for (const int* p : static_cast<const Allocator&>(allocator).Objects()) {
- EXPECT_EQ(*p, i);
- i++;
+ {
+ int i = 0;
+ for (const int* p : static_cast<const Allocator&>(allocator).Objects()) {
+ EXPECT_EQ(*p, i);
+ i++;
+ }
+ EXPECT_EQ(i, N);
}
- EXPECT_EQ(i, N);
- }
}
} // namespace
diff --git a/src/tint/utils/crc32.h b/src/tint/utils/crc32.h
index efe2f0e..5123612 100644
--- a/src/tint/utils/crc32.h
+++ b/src/tint/utils/crc32.h
@@ -24,57 +24,50 @@
/// at compile time.
/// @see https://en.wikipedia.org/wiki/Cyclic_redundancy_check#CRC-32_algorithm
constexpr uint32_t CRC32(const char* s) {
- constexpr uint32_t kLUT[] = {
- 0, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
- 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
- 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
- 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
- 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
- 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
- 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
- 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
- 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
- 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
- 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
- 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
- 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
- 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
- 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
- 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
- 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
- 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
- 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
- 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
- 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
- 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
- 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
- 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
- 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
- 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
- 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
- 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
- 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
- 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
- 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
- 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
- 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
- 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
- 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
- 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
- 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
- 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
- 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
- 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
- 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
- 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
- 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d};
+ constexpr uint32_t kLUT[] = {
+ 0, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535,
+ 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd,
+ 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d,
+ 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
+ 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
+ 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
+ 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac,
+ 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
+ 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab,
+ 0xb6662d3d, 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
+ 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb,
+ 0x086d3d2d, 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
+ 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea,
+ 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 0x4db26158, 0x3ab551ce,
+ 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
+ 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
+ 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409,
+ 0xce61e49f, 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
+ 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739,
+ 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
+ 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, 0x8708a3d2, 0x1e01f268,
+ 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0,
+ 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8,
+ 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
+ 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
+ 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703,
+ 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7,
+ 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
+ 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae,
+ 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
+ 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 0x88085ae6,
+ 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
+ 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d,
+ 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5,
+ 0x47b2cf7f, 0x30b5ffe9, 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
+ 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
+ 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d};
- uint32_t crc = 0xffffffff;
- for (auto* p = s; *p != '\0'; ++p) {
- crc =
- (crc >> 8) ^ kLUT[static_cast<uint8_t>(crc) ^ static_cast<uint8_t>(*p)];
- }
- return crc ^ 0xffffffff;
+ uint32_t crc = 0xffffffff;
+ for (auto* p = s; *p != '\0'; ++p) {
+ crc = (crc >> 8) ^ kLUT[static_cast<uint8_t>(crc) ^ static_cast<uint8_t>(*p)];
+ }
+ return crc ^ 0xffffffff;
}
} // namespace tint::utils
diff --git a/src/tint/utils/crc32_test.cc b/src/tint/utils/crc32_test.cc
index 3e80e78..28dd16f 100644
--- a/src/tint/utils/crc32_test.cc
+++ b/src/tint/utils/crc32_test.cc
@@ -20,15 +20,15 @@
namespace {
TEST(CRC32Test, Compiletime) {
- static_assert(CRC32("") == 0x00000000u);
- static_assert(CRC32("hello world") == 0x0d4a1185u);
- static_assert(CRC32("123456789") == 0xcbf43926u);
+ static_assert(CRC32("") == 0x00000000u);
+ static_assert(CRC32("hello world") == 0x0d4a1185u);
+ static_assert(CRC32("123456789") == 0xcbf43926u);
}
TEST(CRC32Test, Runtime) {
- EXPECT_EQ(CRC32(""), 0x00000000u);
- EXPECT_EQ(CRC32("hello world"), 0x0d4a1185u);
- EXPECT_EQ(CRC32("123456789"), 0xcbf43926u);
+ EXPECT_EQ(CRC32(""), 0x00000000u);
+ EXPECT_EQ(CRC32("hello world"), 0x0d4a1185u);
+ EXPECT_EQ(CRC32("123456789"), 0xcbf43926u);
}
} // namespace
diff --git a/src/tint/utils/debugger.cc b/src/tint/utils/debugger.cc
index aded5b6..3e05bdc 100644
--- a/src/tint/utils/debugger.cc
+++ b/src/tint/utils/debugger.cc
@@ -27,32 +27,31 @@
#ifdef _MSC_VER
#define TINT_DEBUGGER_BREAK_DEFINED
void tint::debugger::Break() {
- if (::IsDebuggerPresent()) {
- ::DebugBreak();
- }
+ if (::IsDebuggerPresent()) {
+ ::DebugBreak();
+ }
}
#elif defined(__linux__)
#define TINT_DEBUGGER_BREAK_DEFINED
void tint::debugger::Break() {
- // A process is being traced (debugged) if "/proc/self/status" contains a
- // line with "TracerPid: <non-zero-digit>...".
- bool is_traced = false;
- std::ifstream fin("/proc/self/status");
- std::string line;
- while (!is_traced && std::getline(fin, line)) {
- const char kPrefix[] = "TracerPid:\t";
- static constexpr int kPrefixLen = sizeof(kPrefix) - 1;
- if (line.length() > kPrefixLen &&
- line.compare(0, kPrefixLen, kPrefix) == 0) {
- is_traced = line[kPrefixLen] != '0';
+ // A process is being traced (debugged) if "/proc/self/status" contains a
+ // line with "TracerPid: <non-zero-digit>...".
+ bool is_traced = false;
+ std::ifstream fin("/proc/self/status");
+ std::string line;
+ while (!is_traced && std::getline(fin, line)) {
+ const char kPrefix[] = "TracerPid:\t";
+ static constexpr int kPrefixLen = sizeof(kPrefix) - 1;
+ if (line.length() > kPrefixLen && line.compare(0, kPrefixLen, kPrefix) == 0) {
+ is_traced = line[kPrefixLen] != '0';
+ }
}
- }
- if (is_traced) {
- raise(SIGTRAP);
- }
+ if (is_traced) {
+ raise(SIGTRAP);
+ }
}
#endif // platform
diff --git a/src/tint/utils/defer.h b/src/tint/utils/defer.h
index ce586f9..f073fb9 100644
--- a/src/tint/utils/defer.h
+++ b/src/tint/utils/defer.h
@@ -24,38 +24,37 @@
/// Defer executes a function or function like object when it is destructed.
template <typename F>
class Defer {
- public:
- /// Constructor
- /// @param f the function to call when the Defer is destructed
- explicit Defer(F&& f) : f_(std::move(f)) {}
+ public:
+ /// Constructor
+ /// @param f the function to call when the Defer is destructed
+ explicit Defer(F&& f) : f_(std::move(f)) {}
- /// Move constructor
- Defer(Defer&&) = default;
+ /// Move constructor
+ Defer(Defer&&) = default;
- /// Destructor
- /// Calls the deferred function
- ~Defer() { f_(); }
+ /// Destructor
+ /// Calls the deferred function
+ ~Defer() { f_(); }
- private:
- Defer(const Defer&) = delete;
- Defer& operator=(const Defer&) = delete;
+ private:
+ Defer(const Defer&) = delete;
+ Defer& operator=(const Defer&) = delete;
- F f_;
+ F f_;
};
/// Constructor
/// @param f the function to call when the Defer is destructed
template <typename F>
inline Defer<F> MakeDefer(F&& f) {
- return Defer<F>(std::forward<F>(f));
+ return Defer<F>(std::forward<F>(f));
}
} // namespace tint::utils
/// TINT_DEFER(S) executes the statement(s) `S` when exiting the current lexical
/// scope.
-#define TINT_DEFER(S) \
- auto TINT_CONCAT(tint_defer_, __COUNTER__) = \
- ::tint::utils::MakeDefer([&] { S; })
+#define TINT_DEFER(S) \
+ auto TINT_CONCAT(tint_defer_, __COUNTER__) = ::tint::utils::MakeDefer([&] { S; })
#endif // SRC_TINT_UTILS_DEFER_H_
diff --git a/src/tint/utils/defer_test.cc b/src/tint/utils/defer_test.cc
index 27fd9b5..8a0bddb 100644
--- a/src/tint/utils/defer_test.cc
+++ b/src/tint/utils/defer_test.cc
@@ -20,22 +20,22 @@
namespace {
TEST(DeferTest, Basic) {
- bool deferCalled = false;
- { TINT_DEFER(deferCalled = true); }
- ASSERT_TRUE(deferCalled);
+ bool deferCalled = false;
+ { TINT_DEFER(deferCalled = true); }
+ ASSERT_TRUE(deferCalled);
}
TEST(DeferTest, DeferOrder) {
- int counter = 0;
- int a = 0, b = 0, c = 0;
- {
- TINT_DEFER(a = ++counter);
- TINT_DEFER(b = ++counter);
- TINT_DEFER(c = ++counter);
- }
- ASSERT_EQ(a, 3);
- ASSERT_EQ(b, 2);
- ASSERT_EQ(c, 1);
+ int counter = 0;
+ int a = 0, b = 0, c = 0;
+ {
+ TINT_DEFER(a = ++counter);
+ TINT_DEFER(b = ++counter);
+ TINT_DEFER(c = ++counter);
+ }
+ ASSERT_EQ(a, 3);
+ ASSERT_EQ(b, 2);
+ ASSERT_EQ(c, 1);
}
} // namespace
diff --git a/src/tint/utils/enum_set.h b/src/tint/utils/enum_set.h
index c5af0f9..19d1a82 100644
--- a/src/tint/utils/enum_set.h
+++ b/src/tint/utils/enum_set.h
@@ -28,194 +28,192 @@
/// enum values in the range [0 .. 63].
template <typename ENUM>
struct EnumSet {
- public:
- /// Enum is the enum type this EnumSet wraps
- using Enum = ENUM;
+ public:
+ /// Enum is the enum type this EnumSet wraps
+ using Enum = ENUM;
- /// Constructor. Initializes the EnumSet with zero.
- constexpr EnumSet() = default;
+ /// Constructor. Initializes the EnumSet with zero.
+ constexpr EnumSet() = default;
- /// Copy constructor.
- /// @param s the set to copy
- constexpr EnumSet(const EnumSet& s) = 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...)) {}
+ /// 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 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}; }
+ /// 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;
+ /// 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 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;
- }
+ /// @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 Iterator to compare this to
- /// @return true if the two iterators are different
- bool operator!=(const Iterator& rhs) const { return !(*this == rhs); }
+ /// @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; }
- private:
- const uint64_t set;
- int8_t pos;
- };
+ /// 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); }
- /// @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;
- }
+ /// 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); }
- /// @returns an iterator to the beginning of the set
- Iterator end() { return Iterator{set, Iterator::kEnd}; }
+ /// @return the underlying value for the EnumSet
+ inline uint64_t Value() const { return set; }
- private:
- static constexpr uint64_t Bit(Enum value) {
- return static_cast<uint64_t>(1) << static_cast<uint64_t>(value);
- }
+ /// Iterator provides read-only, unidirectional iterator over the enums of an
+ /// EnumSet.
+ class Iterator {
+ static constexpr int8_t kEnd = 63;
- static constexpr uint64_t Union() { return 0; }
+ Iterator(uint64_t s, int8_t b) : set(s), pos(b) {}
- template <typename FIRST, typename... VALUES>
- static constexpr uint64_t Union(FIRST first, VALUES... values) {
- return Bit(first) | Union(values...);
- }
+ /// Make the constructor accessible to the EnumSet.
+ friend struct EnumSet;
- uint64_t set = 0;
+ 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.
@@ -224,16 +222,16 @@
/// @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 << ", ";
+ out << "{";
+ bool first = true;
+ for (auto e : set) {
+ if (!first) {
+ out << ", ";
+ }
+ first = false;
+ out << e;
}
- first = false;
- out << e;
- }
- return out << "}";
+ return out << "}";
}
} // namespace tint::utils
@@ -243,12 +241,12 @@
/// 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());
- }
+ 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
diff --git a/src/tint/utils/enum_set_test.cc b/src/tint/utils/enum_set_test.cc
index f0e4e67..e469650 100644
--- a/src/tint/utils/enum_set_test.cc
+++ b/src/tint/utils/enum_set_test.cc
@@ -27,215 +27,215 @@
enum class E { A = 0, B = 3, C = 7 };
std::ostream& operator<<(std::ostream& out, E e) {
- switch (e) {
- case E::A:
- return out << "A";
- case E::B:
- return out << "B";
- case E::C:
- return out << "C";
- }
- return out << "E(" << static_cast<uint32_t>(e) << ")";
+ switch (e) {
+ case E::A:
+ return out << "A";
+ case E::B:
+ return out << "B";
+ case E::C:
+ return out << "C";
+ }
+ return out << "E(" << static_cast<uint32_t>(e) << ")";
}
TEST(EnumSetTest, ConstructEmpty) {
- EnumSet<E> set;
- EXPECT_FALSE(set.Contains(E::A));
- EXPECT_FALSE(set.Contains(E::B));
- EXPECT_FALSE(set.Contains(E::C));
- EXPECT_TRUE(set.Empty());
+ EnumSet<E> set;
+ EXPECT_FALSE(set.Contains(E::A));
+ EXPECT_FALSE(set.Contains(E::B));
+ EXPECT_FALSE(set.Contains(E::C));
+ EXPECT_TRUE(set.Empty());
}
TEST(EnumSetTest, ConstructWithSingle) {
- EnumSet<E> set(E::B);
- EXPECT_FALSE(set.Contains(E::A));
- EXPECT_TRUE(set.Contains(E::B));
- EXPECT_FALSE(set.Contains(E::C));
- EXPECT_FALSE(set.Empty());
+ EnumSet<E> set(E::B);
+ EXPECT_FALSE(set.Contains(E::A));
+ EXPECT_TRUE(set.Contains(E::B));
+ EXPECT_FALSE(set.Contains(E::C));
+ EXPECT_FALSE(set.Empty());
}
TEST(EnumSetTest, ConstructWithMultiple) {
- EnumSet<E> set(E::A, E::C);
- EXPECT_TRUE(set.Contains(E::A));
- EXPECT_FALSE(set.Contains(E::B));
- EXPECT_TRUE(set.Contains(E::C));
- EXPECT_FALSE(set.Empty());
+ EnumSet<E> set(E::A, E::C);
+ EXPECT_TRUE(set.Contains(E::A));
+ EXPECT_FALSE(set.Contains(E::B));
+ EXPECT_TRUE(set.Contains(E::C));
+ EXPECT_FALSE(set.Empty());
}
TEST(EnumSetTest, AssignSet) {
- EnumSet<E> set;
- set = EnumSet<E>(E::A, E::C);
- EXPECT_TRUE(set.Contains(E::A));
- EXPECT_FALSE(set.Contains(E::B));
- EXPECT_TRUE(set.Contains(E::C));
+ EnumSet<E> set;
+ set = EnumSet<E>(E::A, E::C);
+ EXPECT_TRUE(set.Contains(E::A));
+ EXPECT_FALSE(set.Contains(E::B));
+ EXPECT_TRUE(set.Contains(E::C));
}
TEST(EnumSetTest, AssignEnum) {
- EnumSet<E> set(E::A);
- set = E::B;
- EXPECT_FALSE(set.Contains(E::A));
- EXPECT_TRUE(set.Contains(E::B));
- EXPECT_FALSE(set.Contains(E::C));
+ EnumSet<E> set(E::A);
+ set = E::B;
+ EXPECT_FALSE(set.Contains(E::A));
+ EXPECT_TRUE(set.Contains(E::B));
+ EXPECT_FALSE(set.Contains(E::C));
}
TEST(EnumSetTest, AddEnum) {
- EnumSet<E> set;
- set.Add(E::B);
- EXPECT_FALSE(set.Contains(E::A));
- EXPECT_TRUE(set.Contains(E::B));
- EXPECT_FALSE(set.Contains(E::C));
+ EnumSet<E> set;
+ set.Add(E::B);
+ EXPECT_FALSE(set.Contains(E::A));
+ EXPECT_TRUE(set.Contains(E::B));
+ EXPECT_FALSE(set.Contains(E::C));
}
TEST(EnumSetTest, RemoveEnum) {
- EnumSet<E> set(E::A, E::B);
- set.Remove(E::B);
- EXPECT_TRUE(set.Contains(E::A));
- EXPECT_FALSE(set.Contains(E::B));
- EXPECT_FALSE(set.Contains(E::C));
+ EnumSet<E> set(E::A, E::B);
+ set.Remove(E::B);
+ EXPECT_TRUE(set.Contains(E::A));
+ EXPECT_FALSE(set.Contains(E::B));
+ EXPECT_FALSE(set.Contains(E::C));
}
TEST(EnumSetTest, AddEnums) {
- EnumSet<E> set;
- set.Add(E::B, E::C);
- EXPECT_FALSE(set.Contains(E::A));
- EXPECT_TRUE(set.Contains(E::B));
- EXPECT_TRUE(set.Contains(E::C));
+ EnumSet<E> set;
+ set.Add(E::B, E::C);
+ EXPECT_FALSE(set.Contains(E::A));
+ EXPECT_TRUE(set.Contains(E::B));
+ EXPECT_TRUE(set.Contains(E::C));
}
TEST(EnumSetTest, RemoveEnums) {
- EnumSet<E> set(E::A, E::B);
- set.Remove(E::C, E::B);
- EXPECT_TRUE(set.Contains(E::A));
- EXPECT_FALSE(set.Contains(E::B));
- EXPECT_FALSE(set.Contains(E::C));
+ EnumSet<E> set(E::A, E::B);
+ set.Remove(E::C, E::B);
+ EXPECT_TRUE(set.Contains(E::A));
+ EXPECT_FALSE(set.Contains(E::B));
+ EXPECT_FALSE(set.Contains(E::C));
}
TEST(EnumSetTest, AddEnumSet) {
- EnumSet<E> set;
- set.Add(EnumSet<E>{E::B, E::C});
- EXPECT_FALSE(set.Contains(E::A));
- EXPECT_TRUE(set.Contains(E::B));
- EXPECT_TRUE(set.Contains(E::C));
+ EnumSet<E> set;
+ set.Add(EnumSet<E>{E::B, E::C});
+ EXPECT_FALSE(set.Contains(E::A));
+ EXPECT_TRUE(set.Contains(E::B));
+ EXPECT_TRUE(set.Contains(E::C));
}
TEST(EnumSetTest, RemoveEnumSet) {
- EnumSet<E> set(E::A, E::B);
- set.Remove(EnumSet<E>{E::B, E::C});
- EXPECT_TRUE(set.Contains(E::A));
- EXPECT_FALSE(set.Contains(E::B));
- EXPECT_FALSE(set.Contains(E::C));
+ EnumSet<E> set(E::A, E::B);
+ set.Remove(EnumSet<E>{E::B, E::C});
+ EXPECT_TRUE(set.Contains(E::A));
+ EXPECT_FALSE(set.Contains(E::B));
+ EXPECT_FALSE(set.Contains(E::C));
}
TEST(EnumSetTest, OperatorPlusEnum) {
- EnumSet<E> set = EnumSet<E>{E::B} + E::C;
- EXPECT_FALSE(set.Contains(E::A));
- EXPECT_TRUE(set.Contains(E::B));
- EXPECT_TRUE(set.Contains(E::C));
+ EnumSet<E> set = EnumSet<E>{E::B} + E::C;
+ EXPECT_FALSE(set.Contains(E::A));
+ EXPECT_TRUE(set.Contains(E::B));
+ EXPECT_TRUE(set.Contains(E::C));
}
TEST(EnumSetTest, OperatorMinusEnum) {
- EnumSet<E> set = EnumSet<E>{E::A, E::B} - E::B;
- EXPECT_TRUE(set.Contains(E::A));
- EXPECT_FALSE(set.Contains(E::B));
- EXPECT_FALSE(set.Contains(E::C));
+ EnumSet<E> set = EnumSet<E>{E::A, E::B} - E::B;
+ EXPECT_TRUE(set.Contains(E::A));
+ EXPECT_FALSE(set.Contains(E::B));
+ EXPECT_FALSE(set.Contains(E::C));
}
TEST(EnumSetTest, OperatorPlusSet) {
- EnumSet<E> set = EnumSet<E>{E::B} + EnumSet<E>{E::B, E::C};
- EXPECT_FALSE(set.Contains(E::A));
- EXPECT_TRUE(set.Contains(E::B));
- EXPECT_TRUE(set.Contains(E::C));
+ EnumSet<E> set = EnumSet<E>{E::B} + EnumSet<E>{E::B, E::C};
+ EXPECT_FALSE(set.Contains(E::A));
+ EXPECT_TRUE(set.Contains(E::B));
+ EXPECT_TRUE(set.Contains(E::C));
}
TEST(EnumSetTest, OperatorMinusSet) {
- EnumSet<E> set = EnumSet<E>{E::A, E::B} - EnumSet<E>{E::B, E::C};
- EXPECT_TRUE(set.Contains(E::A));
- EXPECT_FALSE(set.Contains(E::B));
- EXPECT_FALSE(set.Contains(E::C));
+ EnumSet<E> set = EnumSet<E>{E::A, E::B} - EnumSet<E>{E::B, E::C};
+ EXPECT_TRUE(set.Contains(E::A));
+ EXPECT_FALSE(set.Contains(E::B));
+ EXPECT_FALSE(set.Contains(E::C));
}
TEST(EnumSetTest, OperatorAnd) {
- EnumSet<E> set = EnumSet<E>{E::A, E::B} & EnumSet<E>{E::B, E::C};
- EXPECT_FALSE(set.Contains(E::A));
- EXPECT_TRUE(set.Contains(E::B));
- EXPECT_FALSE(set.Contains(E::C));
+ EnumSet<E> set = EnumSet<E>{E::A, E::B} & EnumSet<E>{E::B, E::C};
+ EXPECT_FALSE(set.Contains(E::A));
+ EXPECT_TRUE(set.Contains(E::B));
+ EXPECT_FALSE(set.Contains(E::C));
}
TEST(EnumSetTest, EqualitySet) {
- EXPECT_TRUE(EnumSet<E>(E::A, E::B) == EnumSet<E>(E::A, E::B));
- EXPECT_FALSE(EnumSet<E>(E::A, E::B) == EnumSet<E>(E::A, E::C));
+ EXPECT_TRUE(EnumSet<E>(E::A, E::B) == EnumSet<E>(E::A, E::B));
+ EXPECT_FALSE(EnumSet<E>(E::A, E::B) == EnumSet<E>(E::A, E::C));
}
TEST(EnumSetTest, InequalitySet) {
- EXPECT_FALSE(EnumSet<E>(E::A, E::B) != EnumSet<E>(E::A, E::B));
- EXPECT_TRUE(EnumSet<E>(E::A, E::B) != EnumSet<E>(E::A, E::C));
+ EXPECT_FALSE(EnumSet<E>(E::A, E::B) != EnumSet<E>(E::A, E::B));
+ EXPECT_TRUE(EnumSet<E>(E::A, E::B) != EnumSet<E>(E::A, E::C));
}
TEST(EnumSetTest, EqualityEnum) {
- EXPECT_TRUE(EnumSet<E>(E::A) == E::A);
- EXPECT_FALSE(EnumSet<E>(E::B) == E::A);
- EXPECT_FALSE(EnumSet<E>(E::B) == E::C);
- EXPECT_FALSE(EnumSet<E>(E::A, E::B) == E::A);
- EXPECT_FALSE(EnumSet<E>(E::A, E::B) == E::B);
- EXPECT_FALSE(EnumSet<E>(E::A, E::B) == E::C);
+ EXPECT_TRUE(EnumSet<E>(E::A) == E::A);
+ EXPECT_FALSE(EnumSet<E>(E::B) == E::A);
+ EXPECT_FALSE(EnumSet<E>(E::B) == E::C);
+ EXPECT_FALSE(EnumSet<E>(E::A, E::B) == E::A);
+ EXPECT_FALSE(EnumSet<E>(E::A, E::B) == E::B);
+ EXPECT_FALSE(EnumSet<E>(E::A, E::B) == E::C);
}
TEST(EnumSetTest, InequalityEnum) {
- EXPECT_FALSE(EnumSet<E>(E::A) != E::A);
- EXPECT_TRUE(EnumSet<E>(E::B) != E::A);
- EXPECT_TRUE(EnumSet<E>(E::B) != E::C);
- EXPECT_TRUE(EnumSet<E>(E::A, E::B) != E::A);
- EXPECT_TRUE(EnumSet<E>(E::A, E::B) != E::B);
- EXPECT_TRUE(EnumSet<E>(E::A, E::B) != E::C);
+ EXPECT_FALSE(EnumSet<E>(E::A) != E::A);
+ EXPECT_TRUE(EnumSet<E>(E::B) != E::A);
+ EXPECT_TRUE(EnumSet<E>(E::B) != E::C);
+ EXPECT_TRUE(EnumSet<E>(E::A, E::B) != E::A);
+ EXPECT_TRUE(EnumSet<E>(E::A, E::B) != E::B);
+ EXPECT_TRUE(EnumSet<E>(E::A, E::B) != E::C);
}
TEST(EnumSetTest, Hash) {
- auto hash = [&](EnumSet<E> s) { return std::hash<EnumSet<E>>()(s); };
- EXPECT_EQ(hash(EnumSet<E>(E::A, E::B)), hash(EnumSet<E>(E::A, E::B)));
- EXPECT_NE(hash(EnumSet<E>(E::A, E::B)), hash(EnumSet<E>(E::A, E::C)));
+ auto hash = [&](EnumSet<E> s) { return std::hash<EnumSet<E>>()(s); };
+ EXPECT_EQ(hash(EnumSet<E>(E::A, E::B)), hash(EnumSet<E>(E::A, E::B)));
+ EXPECT_NE(hash(EnumSet<E>(E::A, E::B)), hash(EnumSet<E>(E::A, E::C)));
}
TEST(EnumSetTest, Value) {
- EXPECT_EQ(EnumSet<E>().Value(), 0u);
- EXPECT_EQ(EnumSet<E>(E::A).Value(), 1u);
- EXPECT_EQ(EnumSet<E>(E::B).Value(), 8u);
- EXPECT_EQ(EnumSet<E>(E::C).Value(), 128u);
- EXPECT_EQ(EnumSet<E>(E::A, E::C).Value(), 129u);
+ EXPECT_EQ(EnumSet<E>().Value(), 0u);
+ EXPECT_EQ(EnumSet<E>(E::A).Value(), 1u);
+ EXPECT_EQ(EnumSet<E>(E::B).Value(), 8u);
+ EXPECT_EQ(EnumSet<E>(E::C).Value(), 128u);
+ EXPECT_EQ(EnumSet<E>(E::A, E::C).Value(), 129u);
}
TEST(EnumSetTest, Iterator) {
- auto set = EnumSet<E>(E::C, E::A);
+ auto set = EnumSet<E>(E::C, E::A);
- auto it = set.begin();
- EXPECT_EQ(*it, E::A);
- EXPECT_NE(it, set.end());
- ++it;
- EXPECT_EQ(*it, E::C);
- EXPECT_NE(it, set.end());
- ++it;
- EXPECT_EQ(it, set.end());
+ auto it = set.begin();
+ EXPECT_EQ(*it, E::A);
+ EXPECT_NE(it, set.end());
+ ++it;
+ EXPECT_EQ(*it, E::C);
+ EXPECT_NE(it, set.end());
+ ++it;
+ EXPECT_EQ(it, set.end());
}
TEST(EnumSetTest, IteratorEmpty) {
- auto set = EnumSet<E>();
- EXPECT_EQ(set.begin(), set.end());
+ auto set = EnumSet<E>();
+ EXPECT_EQ(set.begin(), set.end());
}
TEST(EnumSetTest, Loop) {
- auto set = EnumSet<E>(E::C, E::A);
+ auto set = EnumSet<E>(E::C, E::A);
- std::vector<E> seen;
- for (auto e : set) {
- seen.emplace_back(e);
- }
+ std::vector<E> seen;
+ for (auto e : set) {
+ seen.emplace_back(e);
+ }
- EXPECT_THAT(seen, ElementsAre(E::A, E::C));
+ EXPECT_THAT(seen, ElementsAre(E::A, E::C));
}
TEST(EnumSetTest, Ostream) {
- std::stringstream ss;
- ss << EnumSet<E>(E::A, E::C);
- EXPECT_EQ(ss.str(), "{A, C}");
+ std::stringstream ss;
+ ss << EnumSet<E>(E::A, E::C);
+ EXPECT_EQ(ss.str(), "{A, C}");
}
} // namespace
diff --git a/src/tint/utils/hash.h b/src/tint/utils/hash.h
index 5ca663b..1bc2edb 100644
--- a/src/tint/utils/hash.h
+++ b/src/tint/utils/hash.h
@@ -32,15 +32,15 @@
/// Specialization of HashCombineOffset for size_t == 4.
template <>
struct HashCombineOffset<4> {
- /// @returns the seed bias value for HashCombine()
- static constexpr inline uint32_t value() { return 0x7f4a7c16; }
+ /// @returns the seed bias value for HashCombine()
+ static constexpr inline uint32_t value() { return 0x7f4a7c16; }
};
/// Specialization of HashCombineOffset for size_t == 8.
template <>
struct HashCombineOffset<8> {
- /// @returns the seed bias value for HashCombine()
- static constexpr inline uint64_t value() { return 0x9e3779b97f4a7c16; }
+ /// @returns the seed bias value for HashCombine()
+ static constexpr inline uint64_t value() { return 0x9e3779b97f4a7c16; }
};
} // namespace detail
@@ -48,64 +48,59 @@
/// HashCombine "hashes" together an existing hash and hashable values.
template <typename T>
void HashCombine(size_t* hash, const T& value) {
- constexpr size_t offset = detail::HashCombineOffset<sizeof(size_t)>::value();
- *hash ^= std::hash<T>()(value) + offset + (*hash << 6) + (*hash >> 2);
+ constexpr size_t offset = detail::HashCombineOffset<sizeof(size_t)>::value();
+ *hash ^= std::hash<T>()(value) + offset + (*hash << 6) + (*hash >> 2);
}
/// HashCombine "hashes" together an existing hash and hashable values.
template <typename T>
void HashCombine(size_t* hash, const std::vector<T>& vector) {
- HashCombine(hash, vector.size());
- for (auto& el : vector) {
- HashCombine(hash, el);
- }
+ HashCombine(hash, vector.size());
+ for (auto& el : vector) {
+ HashCombine(hash, el);
+ }
}
/// HashCombine "hashes" together an existing hash and hashable values.
template <typename T, typename... ARGS>
void HashCombine(size_t* hash, const T& value, const ARGS&... args) {
- HashCombine(hash, value);
- HashCombine(hash, args...);
+ HashCombine(hash, value);
+ HashCombine(hash, args...);
}
/// @returns a hash of the combined arguments. The returned hash is dependent on
/// the order of the arguments.
template <typename... ARGS>
size_t Hash(const ARGS&... args) {
- size_t hash = 102931; // seed with an arbitrary prime
- HashCombine(&hash, args...);
- return hash;
+ size_t hash = 102931; // seed with an arbitrary prime
+ HashCombine(&hash, args...);
+ return hash;
}
/// Wrapper for a hashable type enabling the wrapped value to be used as a key
/// for an unordered_map or unordered_set.
template <typename T>
struct UnorderedKeyWrapper {
- /// The wrapped value
- const T value;
- /// The hash of value
- const size_t hash;
+ /// The wrapped value
+ const T value;
+ /// The hash of value
+ const size_t hash;
- /// Constructor
- /// @param v the value to wrap
- explicit UnorderedKeyWrapper(const T& v) : value(v), hash(Hash(v)) {}
+ /// Constructor
+ /// @param v the value to wrap
+ explicit UnorderedKeyWrapper(const T& v) : value(v), hash(Hash(v)) {}
- /// Move constructor
- /// @param v the value to wrap
- explicit UnorderedKeyWrapper(T&& v)
- : value(std::move(v)), hash(Hash(value)) {}
+ /// Move constructor
+ /// @param v the value to wrap
+ explicit UnorderedKeyWrapper(T&& v) : value(std::move(v)), hash(Hash(value)) {}
- /// @returns true if this wrapper comes before other
- /// @param other the RHS of the operator
- bool operator<(const UnorderedKeyWrapper& other) const {
- return hash < other.hash;
- }
+ /// @returns true if this wrapper comes before other
+ /// @param other the RHS of the operator
+ bool operator<(const UnorderedKeyWrapper& other) const { return hash < other.hash; }
- /// @returns true if this wrapped value is equal to the other wrapped value
- /// @param other the RHS of the operator
- bool operator==(const UnorderedKeyWrapper& other) const {
- return value == other.value;
- }
+ /// @returns true if this wrapped value is equal to the other wrapped value
+ /// @param other the RHS of the operator
+ bool operator==(const UnorderedKeyWrapper& other) const { return value == other.value; }
};
} // namespace tint::utils
@@ -115,13 +110,12 @@
/// Custom std::hash specialization for tint::utils::UnorderedKeyWrapper
template <typename T>
class hash<tint::utils::UnorderedKeyWrapper<T>> {
- public:
- /// @param w the UnorderedKeyWrapper
- /// @return the hash value
- inline std::size_t operator()(
- const tint::utils::UnorderedKeyWrapper<T>& w) const {
- return w.hash;
- }
+ public:
+ /// @param w the UnorderedKeyWrapper
+ /// @return the hash value
+ inline std::size_t operator()(const tint::utils::UnorderedKeyWrapper<T>& w) const {
+ return w.hash;
+ }
};
} // namespace std
diff --git a/src/tint/utils/hash_test.cc b/src/tint/utils/hash_test.cc
index 3f72890..068ac45 100644
--- a/src/tint/utils/hash_test.cc
+++ b/src/tint/utils/hash_test.cc
@@ -23,50 +23,47 @@
namespace {
TEST(HashTests, Basic) {
- EXPECT_EQ(Hash(123), Hash(123));
- EXPECT_NE(Hash(123), Hash(321));
- EXPECT_EQ(Hash(123, 456), Hash(123, 456));
- EXPECT_NE(Hash(123, 456), Hash(456, 123));
- EXPECT_NE(Hash(123, 456), Hash(123));
- EXPECT_EQ(Hash(123, 456, false), Hash(123, 456, false));
- EXPECT_NE(Hash(123, 456, false), Hash(123, 456));
- EXPECT_EQ(Hash(std::string("hello")), Hash(std::string("hello")));
- EXPECT_NE(Hash(std::string("hello")), Hash(std::string("world")));
+ EXPECT_EQ(Hash(123), Hash(123));
+ EXPECT_NE(Hash(123), Hash(321));
+ EXPECT_EQ(Hash(123, 456), Hash(123, 456));
+ EXPECT_NE(Hash(123, 456), Hash(456, 123));
+ EXPECT_NE(Hash(123, 456), Hash(123));
+ EXPECT_EQ(Hash(123, 456, false), Hash(123, 456, false));
+ EXPECT_NE(Hash(123, 456, false), Hash(123, 456));
+ EXPECT_EQ(Hash(std::string("hello")), Hash(std::string("hello")));
+ EXPECT_NE(Hash(std::string("hello")), Hash(std::string("world")));
}
TEST(HashTests, Vector) {
- EXPECT_EQ(Hash(std::vector<int>({})), Hash(std::vector<int>({})));
- EXPECT_EQ(Hash(std::vector<int>({1, 2, 3})),
- Hash(std::vector<int>({1, 2, 3})));
- EXPECT_NE(Hash(std::vector<int>({1, 2, 3})),
- Hash(std::vector<int>({1, 2, 4})));
- EXPECT_NE(Hash(std::vector<int>({1, 2, 3})),
- Hash(std::vector<int>({1, 2, 3, 4})));
+ EXPECT_EQ(Hash(std::vector<int>({})), Hash(std::vector<int>({})));
+ EXPECT_EQ(Hash(std::vector<int>({1, 2, 3})), Hash(std::vector<int>({1, 2, 3})));
+ EXPECT_NE(Hash(std::vector<int>({1, 2, 3})), Hash(std::vector<int>({1, 2, 4})));
+ EXPECT_NE(Hash(std::vector<int>({1, 2, 3})), Hash(std::vector<int>({1, 2, 3, 4})));
}
TEST(HashTests, UnorderedKeyWrapper) {
- using W = UnorderedKeyWrapper<std::vector<int>>;
+ using W = UnorderedKeyWrapper<std::vector<int>>;
- std::unordered_map<W, int> m;
+ std::unordered_map<W, int> m;
- m.emplace(W{{1, 2}}, -1);
- EXPECT_EQ(m.size(), 1u);
- EXPECT_EQ(m[W({1, 2})], -1);
+ m.emplace(W{{1, 2}}, -1);
+ EXPECT_EQ(m.size(), 1u);
+ EXPECT_EQ(m[W({1, 2})], -1);
- m.emplace(W{{3, 2}}, 1);
- EXPECT_EQ(m.size(), 2u);
- EXPECT_EQ(m[W({3, 2})], 1);
- EXPECT_EQ(m[W({1, 2})], -1);
+ m.emplace(W{{3, 2}}, 1);
+ EXPECT_EQ(m.size(), 2u);
+ EXPECT_EQ(m[W({3, 2})], 1);
+ EXPECT_EQ(m[W({1, 2})], -1);
- m.emplace(W{{100}}, 100);
- EXPECT_EQ(m.size(), 3u);
- EXPECT_EQ(m[W({100})], 100);
- EXPECT_EQ(m[W({3, 2})], 1);
- EXPECT_EQ(m[W({1, 2})], -1);
+ m.emplace(W{{100}}, 100);
+ EXPECT_EQ(m.size(), 3u);
+ EXPECT_EQ(m[W({100})], 100);
+ EXPECT_EQ(m[W({3, 2})], 1);
+ EXPECT_EQ(m[W({1, 2})], -1);
- // Reversed vector element order
- EXPECT_EQ(m[W({2, 3})], 0);
- EXPECT_EQ(m[W({2, 1})], 0);
+ // Reversed vector element order
+ EXPECT_EQ(m[W({2, 3})], 0);
+ EXPECT_EQ(m[W({2, 1})], 0);
}
} // namespace
diff --git a/src/tint/utils/io/command.h b/src/tint/utils/io/command.h
index 63ddab8..8aae691 100644
--- a/src/tint/utils/io/command.h
+++ b/src/tint/utils/io/command.h
@@ -24,57 +24,57 @@
/// arguments and an optional stdin string, and then collecting and returning
/// the process's stdout and stderr output as strings.
class Command {
- public:
- /// Output holds the output of the process
- struct Output {
- /// stdout from the process
- std::string out;
- /// stderr from the process
- std::string err;
- /// process error code
- int error_code = 0;
- };
+ public:
+ /// Output holds the output of the process
+ struct Output {
+ /// stdout from the process
+ std::string out;
+ /// stderr from the process
+ std::string err;
+ /// process error code
+ int error_code = 0;
+ };
- /// Constructor
- /// @param path path to the executable
- explicit Command(const std::string& path);
+ /// Constructor
+ /// @param path path to the executable
+ explicit Command(const std::string& path);
- /// Looks for an executable with the given name in the current working
- /// directory, and if not found there, in each of the directories in the
- /// `PATH` environment variable.
- /// @param executable the executable name
- /// @returns a Command which will return true for Found() if the executable
- /// was found.
- static Command LookPath(const std::string& executable);
+ /// Looks for an executable with the given name in the current working
+ /// directory, and if not found there, in each of the directories in the
+ /// `PATH` environment variable.
+ /// @param executable the executable name
+ /// @returns a Command which will return true for Found() if the executable
+ /// was found.
+ static Command LookPath(const std::string& executable);
- /// @return true if the executable exists at the path provided to the
- /// constructor
- bool Found() const;
+ /// @return true if the executable exists at the path provided to the
+ /// constructor
+ bool Found() const;
- /// @returns the path of the command
- const std::string& Path() const { return path_; }
+ /// @returns the path of the command
+ const std::string& Path() const { return path_; }
- /// Invokes the command with the given argument strings, blocking until the
- /// process has returned.
- /// @param args the string arguments to pass to the process
- /// @returns the process output
- template <typename... ARGS>
- Output operator()(ARGS... args) const {
- return Exec({std::forward<ARGS>(args)...});
- }
+ /// Invokes the command with the given argument strings, blocking until the
+ /// process has returned.
+ /// @param args the string arguments to pass to the process
+ /// @returns the process output
+ template <typename... ARGS>
+ Output operator()(ARGS... args) const {
+ return Exec({std::forward<ARGS>(args)...});
+ }
- /// Exec invokes the command with the given argument strings, blocking until
- /// the process has returned.
- /// @param args the string arguments to pass to the process
- /// @returns the process output
- Output Exec(std::initializer_list<std::string> args) const;
+ /// Exec invokes the command with the given argument strings, blocking until
+ /// the process has returned.
+ /// @param args the string arguments to pass to the process
+ /// @returns the process output
+ Output Exec(std::initializer_list<std::string> args) const;
- /// @param input the input data to pipe to the process's stdin
- void SetInput(const std::string& input) { input_ = input; }
+ /// @param input the input data to pipe to the process's stdin
+ void SetInput(const std::string& input) { input_ = input; }
- private:
- std::string const path_;
- std::string input_;
+ private:
+ std::string const path_;
+ std::string input_;
};
} // namespace tint::utils
diff --git a/src/tint/utils/io/command_other.cc b/src/tint/utils/io/command_other.cc
index 5ae73da..cc1997b 100644
--- a/src/tint/utils/io/command_other.cc
+++ b/src/tint/utils/io/command_other.cc
@@ -19,17 +19,17 @@
Command::Command(const std::string&) {}
Command Command::LookPath(const std::string&) {
- return Command("");
+ return Command("");
}
bool Command::Found() const {
- return false;
+ return false;
}
Command::Output Command::Exec(std::initializer_list<std::string>) const {
- Output out;
- out.err = "Command not supported by this target";
- return out;
+ Output out;
+ out.err = "Command not supported by this target";
+ return out;
}
} // namespace tint::utils
diff --git a/src/tint/utils/io/command_posix.cc b/src/tint/utils/io/command_posix.cc
index 3696921..23ee511 100644
--- a/src/tint/utils/io/command_posix.cc
+++ b/src/tint/utils/io/command_posix.cc
@@ -27,102 +27,102 @@
/// File is a simple wrapper around a POSIX file descriptor
class File {
- constexpr static const int kClosed = -1;
+ constexpr static const int kClosed = -1;
- public:
- /// Constructor
- File() : handle_(kClosed) {}
+ public:
+ /// Constructor
+ File() : handle_(kClosed) {}
- /// Constructor
- explicit File(int handle) : handle_(handle) {}
+ /// Constructor
+ explicit File(int handle) : handle_(handle) {}
- /// Destructor
- ~File() { Close(); }
+ /// Destructor
+ ~File() { Close(); }
- /// Move assignment operator
- File& operator=(File&& rhs) {
- Close();
- handle_ = rhs.handle_;
- rhs.handle_ = kClosed;
- return *this;
- }
-
- /// Closes the file (if it wasn't already closed)
- void Close() {
- if (handle_ != kClosed) {
- close(handle_);
+ /// Move assignment operator
+ File& operator=(File&& rhs) {
+ Close();
+ handle_ = rhs.handle_;
+ rhs.handle_ = kClosed;
+ return *this;
}
- handle_ = kClosed;
- }
- /// @returns the file handle
- operator int() { return handle_; }
+ /// Closes the file (if it wasn't already closed)
+ void Close() {
+ if (handle_ != kClosed) {
+ close(handle_);
+ }
+ handle_ = kClosed;
+ }
- /// @returns true if the file is not closed
- operator bool() { return handle_ != kClosed; }
+ /// @returns the file handle
+ operator int() { return handle_; }
- private:
- File(const File&) = delete;
- File& operator=(const File&) = delete;
+ /// @returns true if the file is not closed
+ operator bool() { return handle_ != kClosed; }
- int handle_ = kClosed;
+ private:
+ File(const File&) = delete;
+ File& operator=(const File&) = delete;
+
+ int handle_ = kClosed;
};
/// Pipe is a simple wrapper around a POSIX pipe() function
class Pipe {
- public:
- /// Constructs the pipe
- Pipe() {
- int pipes[2] = {};
- if (pipe(pipes) == 0) {
- read = File(pipes[0]);
- write = File(pipes[1]);
+ public:
+ /// Constructs the pipe
+ Pipe() {
+ int pipes[2] = {};
+ if (pipe(pipes) == 0) {
+ read = File(pipes[0]);
+ write = File(pipes[1]);
+ }
}
- }
- /// Closes both the read and write files (if they're not already closed)
- void Close() {
- read.Close();
- write.Close();
- }
+ /// Closes both the read and write files (if they're not already closed)
+ void Close() {
+ read.Close();
+ write.Close();
+ }
- /// @returns true if the pipe has an open read or write file
- operator bool() { return read || write; }
+ /// @returns true if the pipe has an open read or write file
+ operator bool() { return read || write; }
- /// The reader end of the pipe
- File read;
+ /// The reader end of the pipe
+ File read;
- /// The writer end of the pipe
- File write;
+ /// The writer end of the pipe
+ File write;
};
bool ExecutableExists(const std::string& path) {
- struct stat s {};
- if (stat(path.c_str(), &s) != 0) {
- return false;
- }
- return s.st_mode & S_IXUSR;
+ struct stat s {};
+ if (stat(path.c_str(), &s) != 0) {
+ return false;
+ }
+ return s.st_mode & S_IXUSR;
}
std::string FindExecutable(const std::string& name) {
- if (ExecutableExists(name)) {
- return name;
- }
- if (name.find("/") == std::string::npos) {
- auto* path_env = getenv("PATH");
- if (!path_env) {
- return "";
+ if (ExecutableExists(name)) {
+ return name;
}
- std::istringstream path{path_env};
- std::string dir;
- while (getline(path, dir, ':')) {
- auto test = dir + "/" + name;
- if (ExecutableExists(test)) {
- return test;
- }
+ if (name.find("/") == std::string::npos) {
+ auto* path_env = getenv("PATH");
+ if (!path_env) {
+ return "";
+ }
+ std::istringstream path{path_env};
+ std::string dir;
+ while (getline(path, dir, ':')) {
+ auto test = dir + "/" + name;
+ if (ExecutableExists(test)) {
+ return test;
+ }
+ }
}
- }
- return "";
+ return "";
}
} // namespace
@@ -130,134 +130,133 @@
Command::Command(const std::string& path) : path_(path) {}
Command Command::LookPath(const std::string& executable) {
- return Command(FindExecutable(executable));
+ return Command(FindExecutable(executable));
}
bool Command::Found() const {
- return ExecutableExists(path_);
+ return ExecutableExists(path_);
}
-Command::Output Command::Exec(
- std::initializer_list<std::string> arguments) const {
- if (!Found()) {
- Output out;
- out.err = "Executable not found";
- return out;
- }
+Command::Output Command::Exec(std::initializer_list<std::string> arguments) const {
+ if (!Found()) {
+ Output out;
+ out.err = "Executable not found";
+ return out;
+ }
- // Pipes used for piping std[in,out,err] to / from the target process.
- Pipe stdin_pipe;
- Pipe stdout_pipe;
- Pipe stderr_pipe;
+ // Pipes used for piping std[in,out,err] to / from the target process.
+ Pipe stdin_pipe;
+ Pipe stdout_pipe;
+ Pipe stderr_pipe;
- if (!stdin_pipe || !stdout_pipe || !stderr_pipe) {
- Output output;
- output.err = "Command::Exec(): Failed to create pipes";
- return output;
- }
-
- // execv() and friends replace the current process image with the target
- // process image. To keep process that called this function going, we need to
- // fork() this process into a child and parent process.
- //
- // The child process is responsible for hooking up the pipes to
- // std[in,out,err]_pipes to STD[IN,OUT,ERR]_FILENO and then calling execv() to
- // run the target command.
- //
- // The parent process is responsible for feeding any input to the stdin_pipe
- // and collectting output from the std[out,err]_pipes.
-
- int child_id = fork();
- if (child_id < 0) {
- Output output;
- output.err = "Command::Exec(): fork() failed";
- return output;
- }
-
- if (child_id > 0) {
- // fork() - parent
-
- // Close the stdout and stderr writer pipes.
- // This is required for getting poll() POLLHUP events.
- stdout_pipe.write.Close();
- stderr_pipe.write.Close();
-
- // Write the input to the child process
- if (!input_.empty()) {
- ssize_t n = write(stdin_pipe.write, input_.data(), input_.size());
- if (n != static_cast<ssize_t>(input_.size())) {
+ if (!stdin_pipe || !stdout_pipe || !stderr_pipe) {
Output output;
- output.err = "Command::Exec(): write() for stdin failed";
+ output.err = "Command::Exec(): Failed to create pipes";
return output;
- }
}
- stdin_pipe.write.Close();
- // Accumulate the stdout and stderr output from the child process
- pollfd poll_fds[2];
- poll_fds[0].fd = stdout_pipe.read;
- poll_fds[0].events = POLLIN;
- poll_fds[1].fd = stderr_pipe.read;
- poll_fds[1].events = POLLIN;
+ // execv() and friends replace the current process image with the target
+ // process image. To keep process that called this function going, we need to
+ // fork() this process into a child and parent process.
+ //
+ // The child process is responsible for hooking up the pipes to
+ // std[in,out,err]_pipes to STD[IN,OUT,ERR]_FILENO and then calling execv() to
+ // run the target command.
+ //
+ // The parent process is responsible for feeding any input to the stdin_pipe
+ // and collectting output from the std[out,err]_pipes.
- Output output;
- bool stdout_open = true;
- bool stderr_open = true;
- while (stdout_open || stderr_open) {
- if (poll(poll_fds, 2, -1) < 0) {
- break;
- }
- char buf[256];
- if (poll_fds[0].revents & POLLIN) {
- auto n = read(stdout_pipe.read, buf, sizeof(buf));
- if (n > 0) {
- output.out += std::string(buf, buf + n);
+ int child_id = fork();
+ if (child_id < 0) {
+ Output output;
+ output.err = "Command::Exec(): fork() failed";
+ return output;
+ }
+
+ if (child_id > 0) {
+ // fork() - parent
+
+ // Close the stdout and stderr writer pipes.
+ // This is required for getting poll() POLLHUP events.
+ stdout_pipe.write.Close();
+ stderr_pipe.write.Close();
+
+ // Write the input to the child process
+ if (!input_.empty()) {
+ ssize_t n = write(stdin_pipe.write, input_.data(), input_.size());
+ if (n != static_cast<ssize_t>(input_.size())) {
+ Output output;
+ output.err = "Command::Exec(): write() for stdin failed";
+ return output;
+ }
}
- }
- if (poll_fds[0].revents & POLLHUP) {
- stdout_open = false;
- }
- if (poll_fds[1].revents & POLLIN) {
- auto n = read(stderr_pipe.read, buf, sizeof(buf));
- if (n > 0) {
- output.err += std::string(buf, buf + n);
+ stdin_pipe.write.Close();
+
+ // Accumulate the stdout and stderr output from the child process
+ pollfd poll_fds[2];
+ poll_fds[0].fd = stdout_pipe.read;
+ poll_fds[0].events = POLLIN;
+ poll_fds[1].fd = stderr_pipe.read;
+ poll_fds[1].events = POLLIN;
+
+ Output output;
+ bool stdout_open = true;
+ bool stderr_open = true;
+ while (stdout_open || stderr_open) {
+ if (poll(poll_fds, 2, -1) < 0) {
+ break;
+ }
+ char buf[256];
+ if (poll_fds[0].revents & POLLIN) {
+ auto n = read(stdout_pipe.read, buf, sizeof(buf));
+ if (n > 0) {
+ output.out += std::string(buf, buf + n);
+ }
+ }
+ if (poll_fds[0].revents & POLLHUP) {
+ stdout_open = false;
+ }
+ if (poll_fds[1].revents & POLLIN) {
+ auto n = read(stderr_pipe.read, buf, sizeof(buf));
+ if (n > 0) {
+ output.err += std::string(buf, buf + n);
+ }
+ }
+ if (poll_fds[1].revents & POLLHUP) {
+ stderr_open = false;
+ }
}
- }
- if (poll_fds[1].revents & POLLHUP) {
- stderr_open = false;
- }
+
+ // Get the resulting error code
+ waitpid(child_id, &output.error_code, 0);
+
+ return output;
+ } else {
+ // fork() - child
+
+ // Redirect the stdin, stdout, stderr pipes for the execv process
+ if ((dup2(stdin_pipe.read, STDIN_FILENO) == -1) ||
+ (dup2(stdout_pipe.write, STDOUT_FILENO) == -1) ||
+ (dup2(stderr_pipe.write, STDERR_FILENO) == -1)) {
+ fprintf(stderr, "Command::Exec(): Failed to redirect pipes");
+ exit(errno);
+ }
+
+ // Close the pipes, once redirected above, we're now done with them.
+ stdin_pipe.Close();
+ stdout_pipe.Close();
+ stderr_pipe.Close();
+
+ // Run target executable
+ std::vector<const char*> args;
+ args.emplace_back(path_.c_str());
+ for (auto& arg : arguments) {
+ args.emplace_back(arg.c_str());
+ }
+ args.emplace_back(nullptr);
+ auto res = execv(path_.c_str(), const_cast<char* const*>(args.data()));
+ exit(res);
}
-
- // Get the resulting error code
- waitpid(child_id, &output.error_code, 0);
-
- return output;
- } else {
- // fork() - child
-
- // Redirect the stdin, stdout, stderr pipes for the execv process
- if ((dup2(stdin_pipe.read, STDIN_FILENO) == -1) ||
- (dup2(stdout_pipe.write, STDOUT_FILENO) == -1) ||
- (dup2(stderr_pipe.write, STDERR_FILENO) == -1)) {
- fprintf(stderr, "Command::Exec(): Failed to redirect pipes");
- exit(errno);
- }
-
- // Close the pipes, once redirected above, we're now done with them.
- stdin_pipe.Close();
- stdout_pipe.Close();
- stderr_pipe.Close();
-
- // Run target executable
- std::vector<const char*> args;
- args.emplace_back(path_.c_str());
- for (auto& arg : arguments) {
- args.emplace_back(arg.c_str());
- }
- args.emplace_back(nullptr);
- auto res = execv(path_.c_str(), const_cast<char* const*>(args.data()));
- exit(res);
- }
}
} // namespace tint::utils
diff --git a/src/tint/utils/io/command_test.cc b/src/tint/utils/io/command_test.cc
index 1b8bb83..ed7e29a 100644
--- a/src/tint/utils/io/command_test.cc
+++ b/src/tint/utils/io/command_test.cc
@@ -22,66 +22,66 @@
#ifdef _WIN32
TEST(CommandTest, Echo) {
- auto cmd = Command::LookPath("cmd");
- if (!cmd.Found()) {
- GTEST_SKIP() << "cmd not found on PATH";
- }
+ auto cmd = Command::LookPath("cmd");
+ if (!cmd.Found()) {
+ GTEST_SKIP() << "cmd not found on PATH";
+ }
- auto res = cmd("/C", "echo", "hello world");
- EXPECT_EQ(res.error_code, 0);
- EXPECT_EQ(res.out, "hello world\r\n");
- EXPECT_EQ(res.err, "");
+ auto res = cmd("/C", "echo", "hello world");
+ EXPECT_EQ(res.error_code, 0);
+ EXPECT_EQ(res.out, "hello world\r\n");
+ EXPECT_EQ(res.err, "");
}
#else
TEST(CommandTest, Echo) {
- auto cmd = Command::LookPath("echo");
- if (!cmd.Found()) {
- GTEST_SKIP() << "echo not found on PATH";
- }
+ auto cmd = Command::LookPath("echo");
+ if (!cmd.Found()) {
+ GTEST_SKIP() << "echo not found on PATH";
+ }
- auto res = cmd("hello world");
- EXPECT_EQ(res.error_code, 0);
- EXPECT_EQ(res.out, "hello world\n");
- EXPECT_EQ(res.err, "");
+ auto res = cmd("hello world");
+ EXPECT_EQ(res.error_code, 0);
+ EXPECT_EQ(res.out, "hello world\n");
+ EXPECT_EQ(res.err, "");
}
TEST(CommandTest, Cat) {
- auto cmd = Command::LookPath("cat");
- if (!cmd.Found()) {
- GTEST_SKIP() << "cat not found on PATH";
- }
+ auto cmd = Command::LookPath("cat");
+ if (!cmd.Found()) {
+ GTEST_SKIP() << "cat not found on PATH";
+ }
- cmd.SetInput("hello world");
- auto res = cmd();
- EXPECT_EQ(res.error_code, 0);
- EXPECT_EQ(res.out, "hello world");
- EXPECT_EQ(res.err, "");
+ cmd.SetInput("hello world");
+ auto res = cmd();
+ EXPECT_EQ(res.error_code, 0);
+ EXPECT_EQ(res.out, "hello world");
+ EXPECT_EQ(res.err, "");
}
TEST(CommandTest, True) {
- auto cmd = Command::LookPath("true");
- if (!cmd.Found()) {
- GTEST_SKIP() << "true not found on PATH";
- }
+ auto cmd = Command::LookPath("true");
+ if (!cmd.Found()) {
+ GTEST_SKIP() << "true not found on PATH";
+ }
- auto res = cmd();
- EXPECT_EQ(res.error_code, 0);
- EXPECT_EQ(res.out, "");
- EXPECT_EQ(res.err, "");
+ auto res = cmd();
+ EXPECT_EQ(res.error_code, 0);
+ EXPECT_EQ(res.out, "");
+ EXPECT_EQ(res.err, "");
}
TEST(CommandTest, False) {
- auto cmd = Command::LookPath("false");
- if (!cmd.Found()) {
- GTEST_SKIP() << "false not found on PATH";
- }
+ auto cmd = Command::LookPath("false");
+ if (!cmd.Found()) {
+ GTEST_SKIP() << "false not found on PATH";
+ }
- auto res = cmd();
- EXPECT_NE(res.error_code, 0);
- EXPECT_EQ(res.out, "");
- EXPECT_EQ(res.err, "");
+ auto res = cmd();
+ EXPECT_NE(res.error_code, 0);
+ EXPECT_EQ(res.out, "");
+ EXPECT_EQ(res.err, "");
}
#endif
diff --git a/src/tint/utils/io/command_windows.cc b/src/tint/utils/io/command_windows.cc
index d59f849..f953a85 100644
--- a/src/tint/utils/io/command_windows.cc
+++ b/src/tint/utils/io/command_windows.cc
@@ -25,112 +25,110 @@
/// Handle is a simple wrapper around the Win32 HANDLE
class Handle {
- public:
- /// Constructor
- Handle() : handle_(nullptr) {}
+ public:
+ /// Constructor
+ Handle() : handle_(nullptr) {}
- /// Constructor
- explicit Handle(HANDLE handle) : handle_(handle) {}
+ /// Constructor
+ explicit Handle(HANDLE handle) : handle_(handle) {}
- /// Destructor
- ~Handle() { Close(); }
+ /// Destructor
+ ~Handle() { Close(); }
- /// Move assignment operator
- Handle& operator=(Handle&& rhs) {
- Close();
- handle_ = rhs.handle_;
- rhs.handle_ = nullptr;
- return *this;
- }
-
- /// Closes the handle (if it wasn't already closed)
- void Close() {
- if (handle_) {
- CloseHandle(handle_);
+ /// Move assignment operator
+ Handle& operator=(Handle&& rhs) {
+ Close();
+ handle_ = rhs.handle_;
+ rhs.handle_ = nullptr;
+ return *this;
}
- handle_ = nullptr;
- }
- /// @returns the handle
- operator HANDLE() { return handle_; }
+ /// Closes the handle (if it wasn't already closed)
+ void Close() {
+ if (handle_) {
+ CloseHandle(handle_);
+ }
+ handle_ = nullptr;
+ }
- /// @returns true if the handle is not invalid
- operator bool() { return handle_ != nullptr; }
+ /// @returns the handle
+ operator HANDLE() { return handle_; }
- private:
- Handle(const Handle&) = delete;
- Handle& operator=(const Handle&) = delete;
+ /// @returns true if the handle is not invalid
+ operator bool() { return handle_ != nullptr; }
- HANDLE handle_ = nullptr;
+ private:
+ Handle(const Handle&) = delete;
+ Handle& operator=(const Handle&) = delete;
+
+ HANDLE handle_ = nullptr;
};
/// Pipe is a simple wrapper around a Win32 CreatePipe() function
class Pipe {
- public:
- /// Constructs the pipe
- explicit Pipe(bool for_read) {
- SECURITY_ATTRIBUTES sa;
- sa.nLength = sizeof(SECURITY_ATTRIBUTES);
- sa.bInheritHandle = TRUE;
- sa.lpSecurityDescriptor = nullptr;
+ public:
+ /// Constructs the pipe
+ explicit Pipe(bool for_read) {
+ SECURITY_ATTRIBUTES sa;
+ sa.nLength = sizeof(SECURITY_ATTRIBUTES);
+ sa.bInheritHandle = TRUE;
+ sa.lpSecurityDescriptor = nullptr;
- HANDLE hread;
- HANDLE hwrite;
- if (CreatePipe(&hread, &hwrite, &sa, 0)) {
- read = Handle(hread);
- write = Handle(hwrite);
- // Ensure the read handle to the pipe is not inherited
- if (!SetHandleInformation(for_read ? read : write, HANDLE_FLAG_INHERIT,
- 0)) {
- read.Close();
- write.Close();
- }
+ HANDLE hread;
+ HANDLE hwrite;
+ if (CreatePipe(&hread, &hwrite, &sa, 0)) {
+ read = Handle(hread);
+ write = Handle(hwrite);
+ // Ensure the read handle to the pipe is not inherited
+ if (!SetHandleInformation(for_read ? read : write, HANDLE_FLAG_INHERIT, 0)) {
+ read.Close();
+ write.Close();
+ }
+ }
}
- }
- /// @returns true if the pipe has an open read or write file
- operator bool() { return read || write; }
+ /// @returns true if the pipe has an open read or write file
+ operator bool() { return read || write; }
- /// The reader end of the pipe
- Handle read;
+ /// The reader end of the pipe
+ Handle read;
- /// The writer end of the pipe
- Handle write;
+ /// The writer end of the pipe
+ Handle write;
};
bool ExecutableExists(const std::string& path) {
- DWORD type = 0;
- return GetBinaryTypeA(path.c_str(), &type);
+ DWORD type = 0;
+ return GetBinaryTypeA(path.c_str(), &type);
}
std::string FindExecutable(const std::string& name) {
- if (ExecutableExists(name)) {
- return name;
- }
- if (ExecutableExists(name + ".exe")) {
- return name + ".exe";
- }
- if (name.find("/") == std::string::npos &&
- name.find("\\") == std::string::npos) {
- char* path_env = nullptr;
- size_t path_env_len = 0;
- if (_dupenv_s(&path_env, &path_env_len, "PATH")) {
- return "";
+ if (ExecutableExists(name)) {
+ return name;
}
- std::istringstream path{path_env};
- free(path_env);
- std::string dir;
- while (getline(path, dir, ';')) {
- auto test = dir + "\\" + name;
- if (ExecutableExists(test)) {
- return test;
- }
- if (ExecutableExists(test + ".exe")) {
- return test + ".exe";
- }
+ if (ExecutableExists(name + ".exe")) {
+ return name + ".exe";
}
- }
- return "";
+ if (name.find("/") == std::string::npos && name.find("\\") == std::string::npos) {
+ char* path_env = nullptr;
+ size_t path_env_len = 0;
+ if (_dupenv_s(&path_env, &path_env_len, "PATH")) {
+ return "";
+ }
+ std::istringstream path{path_env};
+ free(path_env);
+ std::string dir;
+ while (getline(path, dir, ';')) {
+ auto test = dir + "\\" + name;
+ if (ExecutableExists(test)) {
+ return test;
+ }
+ if (ExecutableExists(test + ".exe")) {
+ return test + ".exe";
+ }
+ }
+ }
+ return "";
}
} // namespace
@@ -138,110 +136,106 @@
Command::Command(const std::string& path) : path_(path) {}
Command Command::LookPath(const std::string& executable) {
- return Command(FindExecutable(executable));
+ return Command(FindExecutable(executable));
}
bool Command::Found() const {
- return ExecutableExists(path_);
+ return ExecutableExists(path_);
}
-Command::Output Command::Exec(
- std::initializer_list<std::string> arguments) const {
- Pipe stdout_pipe(true);
- Pipe stderr_pipe(true);
- Pipe stdin_pipe(false);
- if (!stdin_pipe || !stdout_pipe || !stderr_pipe) {
+Command::Output Command::Exec(std::initializer_list<std::string> arguments) const {
+ Pipe stdout_pipe(true);
+ Pipe stderr_pipe(true);
+ Pipe stdin_pipe(false);
+ if (!stdin_pipe || !stdout_pipe || !stderr_pipe) {
+ Output output;
+ output.err = "Command::Exec(): Failed to create pipes";
+ return output;
+ }
+
+ if (!input_.empty()) {
+ if (!WriteFile(stdin_pipe.write, input_.data(), input_.size(), nullptr, nullptr)) {
+ Output output;
+ output.err = "Command::Exec() Failed to write stdin";
+ return output;
+ }
+ }
+ stdin_pipe.write.Close();
+
+ STARTUPINFOA si{};
+ si.cb = sizeof(si);
+ si.dwFlags |= STARTF_USESTDHANDLES;
+ si.hStdOutput = stdout_pipe.write;
+ si.hStdError = stderr_pipe.write;
+ si.hStdInput = stdin_pipe.read;
+
+ std::stringstream args;
+ args << path_;
+ for (auto& arg : arguments) {
+ args << " " << arg;
+ }
+
+ PROCESS_INFORMATION pi{};
+ if (!CreateProcessA(nullptr, // No module name (use command line)
+ const_cast<LPSTR>(args.str().c_str()), // Command line
+ nullptr, // Process handle not inheritable
+ nullptr, // Thread handle not inheritable
+ TRUE, // Handles are inherited
+ 0, // No creation flags
+ nullptr, // Use parent's environment block
+ nullptr, // Use parent's starting directory
+ &si, // Pointer to STARTUPINFO structure
+ &pi)) { // Pointer to PROCESS_INFORMATION structure
+ Output out;
+ out.err = "Command::Exec() CreateProcess() failed";
+ return out;
+ }
+
+ stdin_pipe.read.Close();
+ stdout_pipe.write.Close();
+ stderr_pipe.write.Close();
+
+ struct StreamReadThreadArgs {
+ HANDLE stream;
+ std::string output;
+ };
+
+ auto stream_read_thread = [](LPVOID user) -> DWORD {
+ auto* thread_args = reinterpret_cast<StreamReadThreadArgs*>(user);
+ DWORD n = 0;
+ char buf[256];
+ while (ReadFile(thread_args->stream, buf, sizeof(buf), &n, NULL)) {
+ auto s = std::string(buf, buf + n);
+ thread_args->output += std::string(buf, buf + n);
+ }
+ return 0;
+ };
+
+ StreamReadThreadArgs stdout_read_args{stdout_pipe.read, {}};
+ auto* stdout_read_thread =
+ ::CreateThread(nullptr, 0, stream_read_thread, &stdout_read_args, 0, nullptr);
+
+ StreamReadThreadArgs stderr_read_args{stderr_pipe.read, {}};
+ auto* stderr_read_thread =
+ ::CreateThread(nullptr, 0, stream_read_thread, &stderr_read_args, 0, nullptr);
+
+ HANDLE handles[] = {pi.hProcess, stdout_read_thread, stderr_read_thread};
+ constexpr DWORD num_handles = sizeof(handles) / sizeof(handles[0]);
+
Output output;
- output.err = "Command::Exec(): Failed to create pipes";
+
+ auto res = WaitForMultipleObjects(num_handles, handles, /* wait_all = */ TRUE, INFINITE);
+ if (res >= WAIT_OBJECT_0 && res < WAIT_OBJECT_0 + num_handles) {
+ output.out = stdout_read_args.output;
+ output.err = stderr_read_args.output;
+ DWORD exit_code = 0;
+ GetExitCodeProcess(pi.hProcess, &exit_code);
+ output.error_code = static_cast<int>(exit_code);
+ } else {
+ output.err = "Command::Exec() WaitForMultipleObjects() returned " + std::to_string(res);
+ }
+
return output;
- }
-
- if (!input_.empty()) {
- if (!WriteFile(stdin_pipe.write, input_.data(), input_.size(), nullptr,
- nullptr)) {
- Output output;
- output.err = "Command::Exec() Failed to write stdin";
- return output;
- }
- }
- stdin_pipe.write.Close();
-
- STARTUPINFOA si{};
- si.cb = sizeof(si);
- si.dwFlags |= STARTF_USESTDHANDLES;
- si.hStdOutput = stdout_pipe.write;
- si.hStdError = stderr_pipe.write;
- si.hStdInput = stdin_pipe.read;
-
- std::stringstream args;
- args << path_;
- for (auto& arg : arguments) {
- args << " " << arg;
- }
-
- PROCESS_INFORMATION pi{};
- if (!CreateProcessA(nullptr, // No module name (use command line)
- const_cast<LPSTR>(args.str().c_str()), // Command line
- nullptr, // Process handle not inheritable
- nullptr, // Thread handle not inheritable
- TRUE, // Handles are inherited
- 0, // No creation flags
- nullptr, // Use parent's environment block
- nullptr, // Use parent's starting directory
- &si, // Pointer to STARTUPINFO structure
- &pi)) { // Pointer to PROCESS_INFORMATION structure
- Output out;
- out.err = "Command::Exec() CreateProcess() failed";
- return out;
- }
-
- stdin_pipe.read.Close();
- stdout_pipe.write.Close();
- stderr_pipe.write.Close();
-
- struct StreamReadThreadArgs {
- HANDLE stream;
- std::string output;
- };
-
- auto stream_read_thread = [](LPVOID user) -> DWORD {
- auto* thread_args = reinterpret_cast<StreamReadThreadArgs*>(user);
- DWORD n = 0;
- char buf[256];
- while (ReadFile(thread_args->stream, buf, sizeof(buf), &n, NULL)) {
- auto s = std::string(buf, buf + n);
- thread_args->output += std::string(buf, buf + n);
- }
- return 0;
- };
-
- StreamReadThreadArgs stdout_read_args{stdout_pipe.read, {}};
- auto* stdout_read_thread = ::CreateThread(nullptr, 0, stream_read_thread,
- &stdout_read_args, 0, nullptr);
-
- StreamReadThreadArgs stderr_read_args{stderr_pipe.read, {}};
- auto* stderr_read_thread = ::CreateThread(nullptr, 0, stream_read_thread,
- &stderr_read_args, 0, nullptr);
-
- HANDLE handles[] = {pi.hProcess, stdout_read_thread, stderr_read_thread};
- constexpr DWORD num_handles = sizeof(handles) / sizeof(handles[0]);
-
- Output output;
-
- auto res = WaitForMultipleObjects(num_handles, handles, /* wait_all = */ TRUE,
- INFINITE);
- if (res >= WAIT_OBJECT_0 && res < WAIT_OBJECT_0 + num_handles) {
- output.out = stdout_read_args.output;
- output.err = stderr_read_args.output;
- DWORD exit_code = 0;
- GetExitCodeProcess(pi.hProcess, &exit_code);
- output.error_code = static_cast<int>(exit_code);
- } else {
- output.err = "Command::Exec() WaitForMultipleObjects() returned " +
- std::to_string(res);
- }
-
- return output;
}
} // namespace tint::utils
diff --git a/src/tint/utils/io/tmpfile.h b/src/tint/utils/io/tmpfile.h
index 6f81a891e..24e7208 100644
--- a/src/tint/utils/io/tmpfile.h
+++ b/src/tint/utils/io/tmpfile.h
@@ -23,50 +23,50 @@
/// TmpFile constructs a temporary file that can be written to, and is
/// automatically deleted on destruction.
class TmpFile {
- public:
- /// Constructor.
- /// Creates a new temporary file which can be written to.
- /// The temporary file will be automatically deleted on destruction.
- /// @param extension optional file extension to use with the file. The file
- /// have no extension by default.
- explicit TmpFile(std::string extension = "");
+ public:
+ /// Constructor.
+ /// Creates a new temporary file which can be written to.
+ /// The temporary file will be automatically deleted on destruction.
+ /// @param extension optional file extension to use with the file. The file
+ /// have no extension by default.
+ explicit TmpFile(std::string extension = "");
- /// Destructor.
- /// Deletes the temporary file.
- ~TmpFile();
+ /// Destructor.
+ /// Deletes the temporary file.
+ ~TmpFile();
- /// @return true if the temporary file was successfully created.
- operator bool() { return !path_.empty(); }
+ /// @return true if the temporary file was successfully created.
+ operator bool() { return !path_.empty(); }
- /// @return the path to the temporary file
- std::string Path() const { return path_; }
+ /// @return the path to the temporary file
+ std::string Path() const { return path_; }
- /// Opens the temporary file and appends |size| bytes from |data| to the end
- /// of the temporary file. The temporary file is closed again before
- /// returning, allowing other processes to open the file on operating systems
- /// that require exclusive ownership of opened files.
- /// @param data the data to write to the end of the file
- /// @param size the number of bytes to write from data
- /// @returns true on success, otherwise false
- bool Append(const void* data, size_t size) const;
+ /// Opens the temporary file and appends |size| bytes from |data| to the end
+ /// of the temporary file. The temporary file is closed again before
+ /// returning, allowing other processes to open the file on operating systems
+ /// that require exclusive ownership of opened files.
+ /// @param data the data to write to the end of the file
+ /// @param size the number of bytes to write from data
+ /// @returns true on success, otherwise false
+ bool Append(const void* data, size_t size) const;
- /// Appends the argument to the end of the file.
- /// @param data the data to write to the end of the file
- /// @return a reference to this TmpFile
- template <typename T>
- inline TmpFile& operator<<(T&& data) {
- std::stringstream ss;
- ss << data;
- std::string str = ss.str();
- Append(str.data(), str.size());
- return *this;
- }
+ /// Appends the argument to the end of the file.
+ /// @param data the data to write to the end of the file
+ /// @return a reference to this TmpFile
+ template <typename T>
+ inline TmpFile& operator<<(T&& data) {
+ std::stringstream ss;
+ ss << data;
+ std::string str = ss.str();
+ Append(str.data(), str.size());
+ return *this;
+ }
- private:
- TmpFile(const TmpFile&) = delete;
- TmpFile& operator=(const TmpFile&) = delete;
+ private:
+ TmpFile(const TmpFile&) = delete;
+ TmpFile& operator=(const TmpFile&) = delete;
- std::string path_;
+ std::string path_;
};
} // namespace tint::utils
diff --git a/src/tint/utils/io/tmpfile_other.cc b/src/tint/utils/io/tmpfile_other.cc
index 7ddbb58..14c8660 100644
--- a/src/tint/utils/io/tmpfile_other.cc
+++ b/src/tint/utils/io/tmpfile_other.cc
@@ -21,7 +21,7 @@
TmpFile::~TmpFile() = default;
bool TmpFile::Append(const void*, size_t) const {
- return false;
+ return false;
}
} // namespace tint::utils
diff --git a/src/tint/utils/io/tmpfile_posix.cc b/src/tint/utils/io/tmpfile_posix.cc
index 00c20fe..ba84afd 100644
--- a/src/tint/utils/io/tmpfile_posix.cc
+++ b/src/tint/utils/io/tmpfile_posix.cc
@@ -24,45 +24,43 @@
namespace {
std::string TmpFilePath(std::string ext) {
- char const* dir = getenv("TMPDIR");
- if (dir == nullptr) {
- dir = "/tmp";
- }
+ char const* dir = getenv("TMPDIR");
+ if (dir == nullptr) {
+ dir = "/tmp";
+ }
- // mkstemps requires an `int` for the file extension name but STL represents
- // size_t. Pre-C++20 there the behavior for unsigned-to-signed conversion
- // (when the source value exceeds the representable range) is implementation
- // defined. While such a large file extension is unlikely in practice, we
- // enforce this here at runtime.
- TINT_ASSERT(Utils, ext.length() <=
- static_cast<size_t>(std::numeric_limits<int>::max()));
- std::string name = std::string(dir) + "/tint_XXXXXX" + ext;
- int file = mkstemps(&name[0], static_cast<int>(ext.length()));
- if (file != -1) {
- close(file);
- return name;
- }
- return "";
+ // mkstemps requires an `int` for the file extension name but STL represents
+ // size_t. Pre-C++20 there the behavior for unsigned-to-signed conversion
+ // (when the source value exceeds the representable range) is implementation
+ // defined. While such a large file extension is unlikely in practice, we
+ // enforce this here at runtime.
+ TINT_ASSERT(Utils, ext.length() <= static_cast<size_t>(std::numeric_limits<int>::max()));
+ std::string name = std::string(dir) + "/tint_XXXXXX" + ext;
+ int file = mkstemps(&name[0], static_cast<int>(ext.length()));
+ if (file != -1) {
+ close(file);
+ return name;
+ }
+ return "";
}
} // namespace
-TmpFile::TmpFile(std::string extension)
- : path_(TmpFilePath(std::move(extension))) {}
+TmpFile::TmpFile(std::string extension) : path_(TmpFilePath(std::move(extension))) {}
TmpFile::~TmpFile() {
- if (!path_.empty()) {
- remove(path_.c_str());
- }
+ if (!path_.empty()) {
+ remove(path_.c_str());
+ }
}
bool TmpFile::Append(const void* data, size_t size) const {
- if (auto* file = fopen(path_.c_str(), "ab")) {
- fwrite(data, size, 1, file);
- fclose(file);
- return true;
- }
- return false;
+ if (auto* file = fopen(path_.c_str(), "ab")) {
+ fwrite(data, size, 1, file);
+ fclose(file);
+ return true;
+ }
+ return false;
}
} // namespace tint::utils
diff --git a/src/tint/utils/io/tmpfile_test.cc b/src/tint/utils/io/tmpfile_test.cc
index d312922..4fe103d 100644
--- a/src/tint/utils/io/tmpfile_test.cc
+++ b/src/tint/utils/io/tmpfile_test.cc
@@ -22,66 +22,66 @@
namespace {
TEST(TmpFileTest, WriteReadAppendDelete) {
- std::string path;
- {
- TmpFile tmp;
- if (!tmp) {
- GTEST_SKIP() << "Unable to create a temporary file";
- }
-
- path = tmp.Path();
-
- // Write a string to the temporary file
- tmp << "hello world\n";
-
- // Check the content of the file
+ std::string path;
{
- std::ifstream file(path);
- ASSERT_TRUE(file);
- std::string line;
- EXPECT_TRUE(std::getline(file, line));
- EXPECT_EQ(line, "hello world");
- EXPECT_FALSE(std::getline(file, line));
+ TmpFile tmp;
+ if (!tmp) {
+ GTEST_SKIP() << "Unable to create a temporary file";
+ }
+
+ path = tmp.Path();
+
+ // Write a string to the temporary file
+ tmp << "hello world\n";
+
+ // Check the content of the file
+ {
+ std::ifstream file(path);
+ ASSERT_TRUE(file);
+ std::string line;
+ EXPECT_TRUE(std::getline(file, line));
+ EXPECT_EQ(line, "hello world");
+ EXPECT_FALSE(std::getline(file, line));
+ }
+
+ // Write some more content to the file
+ tmp << 42;
+
+ // Check the content of the file again
+ {
+ std::ifstream file(path);
+ ASSERT_TRUE(file);
+ std::string line;
+ EXPECT_TRUE(std::getline(file, line));
+ EXPECT_EQ(line, "hello world");
+ EXPECT_TRUE(std::getline(file, line));
+ EXPECT_EQ(line, "42");
+ EXPECT_FALSE(std::getline(file, line));
+ }
}
- // Write some more content to the file
- tmp << 42;
-
- // Check the content of the file again
- {
- std::ifstream file(path);
- ASSERT_TRUE(file);
- std::string line;
- EXPECT_TRUE(std::getline(file, line));
- EXPECT_EQ(line, "hello world");
- EXPECT_TRUE(std::getline(file, line));
- EXPECT_EQ(line, "42");
- EXPECT_FALSE(std::getline(file, line));
- }
- }
-
- // Check the file has been deleted when it fell out of scope
- std::ifstream file(path);
- ASSERT_FALSE(file);
+ // Check the file has been deleted when it fell out of scope
+ std::ifstream file(path);
+ ASSERT_FALSE(file);
}
TEST(TmpFileTest, FileExtension) {
- const std::string kExt = ".foo";
- std::string path;
- {
- TmpFile tmp(kExt);
- if (!tmp) {
- GTEST_SKIP() << "Unable create a temporary file";
+ const std::string kExt = ".foo";
+ std::string path;
+ {
+ TmpFile tmp(kExt);
+ if (!tmp) {
+ GTEST_SKIP() << "Unable create a temporary file";
+ }
+ path = tmp.Path();
}
- path = tmp.Path();
- }
- ASSERT_GT(path.length(), kExt.length());
- EXPECT_EQ(kExt, path.substr(path.length() - kExt.length()));
+ ASSERT_GT(path.length(), kExt.length());
+ EXPECT_EQ(kExt, path.substr(path.length() - kExt.length()));
- // Check the file has been deleted when it fell out of scope
- std::ifstream file(path);
- ASSERT_FALSE(file);
+ // Check the file has been deleted when it fell out of scope
+ std::ifstream file(path);
+ ASSERT_FALSE(file);
}
} // namespace
diff --git a/src/tint/utils/io/tmpfile_windows.cc b/src/tint/utils/io/tmpfile_windows.cc
index 40dffc8..3c8e5f7 100644
--- a/src/tint/utils/io/tmpfile_windows.cc
+++ b/src/tint/utils/io/tmpfile_windows.cc
@@ -22,20 +22,20 @@
namespace {
std::string TmpFilePath(const std::string& ext) {
- char name[L_tmpnam];
- // As we're adding an extension, to ensure the file is really unique, try
- // creating it, failing if it already exists.
- while (tmpnam_s(name, L_tmpnam - 1) == 0) {
- std::string name_with_ext = std::string(name) + ext;
- FILE* f = nullptr;
- // The "x" arg forces the function to fail if the file already exists.
- fopen_s(&f, name_with_ext.c_str(), "wbx");
- if (f) {
- fclose(f);
- return name_with_ext;
+ char name[L_tmpnam];
+ // As we're adding an extension, to ensure the file is really unique, try
+ // creating it, failing if it already exists.
+ while (tmpnam_s(name, L_tmpnam - 1) == 0) {
+ std::string name_with_ext = std::string(name) + ext;
+ FILE* f = nullptr;
+ // The "x" arg forces the function to fail if the file already exists.
+ fopen_s(&f, name_with_ext.c_str(), "wbx");
+ if (f) {
+ fclose(f);
+ return name_with_ext;
+ }
}
- }
- return {};
+ return {};
}
} // namespace
@@ -43,19 +43,19 @@
TmpFile::TmpFile(std::string ext) : path_(TmpFilePath(ext)) {}
TmpFile::~TmpFile() {
- if (!path_.empty()) {
- remove(path_.c_str());
- }
+ if (!path_.empty()) {
+ remove(path_.c_str());
+ }
}
bool TmpFile::Append(const void* data, size_t size) const {
- FILE* file = nullptr;
- if (fopen_s(&file, path_.c_str(), "ab") != 0) {
- return false;
- }
- fwrite(data, size, 1, file);
- fclose(file);
- return true;
+ FILE* file = nullptr;
+ if (fopen_s(&file, path_.c_str(), "ab") != 0) {
+ return false;
+ }
+ fwrite(data, size, 1, file);
+ fclose(file);
+ return true;
}
} // namespace tint::utils
diff --git a/src/tint/utils/map.h b/src/tint/utils/map.h
index 12c93d4..0a13730 100644
--- a/src/tint/utils/map.h
+++ b/src/tint/utils/map.h
@@ -28,11 +28,9 @@
/// @return the map item value, or `if_missing` if the map does not contain the
/// given key
template <typename K, typename V, typename H, typename C, typename KV = K>
-V Lookup(const std::unordered_map<K, V, H, C>& map,
- const KV& key,
- const V& if_missing = {}) {
- auto it = map.find(key);
- return it != map.end() ? it->second : if_missing;
+V Lookup(const std::unordered_map<K, V, H, C>& map, const KV& key, const V& if_missing = {}) {
+ auto it = map.find(key);
+ return it != map.end() ? it->second : if_missing;
}
/// GetOrCreate is a utility function for lazily adding to an unordered map.
@@ -43,16 +41,14 @@
/// @param create a callable function-like object with the signature `V()`
/// @return the value of the item with the given key, or the newly created item
template <typename K, typename V, typename H, typename C, typename CREATE>
-V GetOrCreate(std::unordered_map<K, V, H, C>& map,
- const K& key,
- CREATE&& create) {
- auto it = map.find(key);
- if (it != map.end()) {
- return it->second;
- }
- V value = create();
- map.emplace(key, value);
- return value;
+V GetOrCreate(std::unordered_map<K, V, H, C>& map, const K& key, CREATE&& create) {
+ auto it = map.find(key);
+ if (it != map.end()) {
+ return it->second;
+ }
+ V value = create();
+ map.emplace(key, value);
+ return value;
}
} // namespace tint::utils
diff --git a/src/tint/utils/map_test.cc b/src/tint/utils/map_test.cc
index ae35aeb..f0d9392 100644
--- a/src/tint/utils/map_test.cc
+++ b/src/tint/utils/map_test.cc
@@ -22,34 +22,34 @@
namespace {
TEST(Lookup, Test) {
- std::unordered_map<int, int> map;
- map.emplace(10, 1);
- EXPECT_EQ(Lookup(map, 10, 0), 1); // exists, with if_missing
- EXPECT_EQ(Lookup(map, 10), 1); // exists, without if_missing
- EXPECT_EQ(Lookup(map, 20, 50), 50); // missing, with if_missing
- EXPECT_EQ(Lookup(map, 20), 0); // missing, without if_missing
+ std::unordered_map<int, int> map;
+ map.emplace(10, 1);
+ EXPECT_EQ(Lookup(map, 10, 0), 1); // exists, with if_missing
+ EXPECT_EQ(Lookup(map, 10), 1); // exists, without if_missing
+ EXPECT_EQ(Lookup(map, 20, 50), 50); // missing, with if_missing
+ EXPECT_EQ(Lookup(map, 20), 0); // missing, without if_missing
}
TEST(GetOrCreateTest, NewKey) {
- std::unordered_map<int, int> map;
- EXPECT_EQ(GetOrCreate(map, 1, [&] { return 2; }), 2);
- EXPECT_EQ(map.size(), 1u);
- EXPECT_EQ(map[1], 2);
+ std::unordered_map<int, int> map;
+ EXPECT_EQ(GetOrCreate(map, 1, [&] { return 2; }), 2);
+ EXPECT_EQ(map.size(), 1u);
+ EXPECT_EQ(map[1], 2);
}
TEST(GetOrCreateTest, ExistingKey) {
- std::unordered_map<int, int> map;
- map[1] = 2;
- bool called = false;
- EXPECT_EQ(GetOrCreate(map, 1,
- [&] {
- called = true;
- return -2;
- }),
- 2);
- EXPECT_EQ(called, false);
- EXPECT_EQ(map.size(), 1u);
- EXPECT_EQ(map[1], 2);
+ std::unordered_map<int, int> map;
+ map[1] = 2;
+ bool called = false;
+ EXPECT_EQ(GetOrCreate(map, 1,
+ [&] {
+ called = true;
+ return -2;
+ }),
+ 2);
+ EXPECT_EQ(called, false);
+ EXPECT_EQ(map.size(), 1u);
+ EXPECT_EQ(map[1], 2);
}
} // namespace
diff --git a/src/tint/utils/math.h b/src/tint/utils/math.h
index c6d7d46..3d8874a 100644
--- a/src/tint/utils/math.h
+++ b/src/tint/utils/math.h
@@ -27,7 +27,7 @@
/// @note `alignment` must be positive. An alignment of zero will cause a DBZ.
template <typename T>
inline T RoundUp(T alignment, T value) {
- return ((value + alignment - 1) / alignment) * alignment;
+ return ((value + alignment - 1) / alignment) * alignment;
}
/// @param value the value to check whether it is a power-of-two
@@ -35,19 +35,19 @@
/// @note `value` must be positive if `T` is signed
template <typename T>
inline bool IsPowerOfTwo(T value) {
- return (value & (value - 1)) == 0;
+ return (value & (value - 1)) == 0;
}
/// @param value the input value
/// @returns the largest power of two that `value` is a multiple of
template <typename T>
inline std::enable_if_t<std::is_unsigned<T>::value, T> MaxAlignOf(T value) {
- T pot = 1;
- while (value && ((value & 1u) == 0)) {
- pot <<= 1;
- value >>= 1;
- }
- return pot;
+ T pot = 1;
+ while (value && ((value & 1u) == 0)) {
+ pot <<= 1;
+ value >>= 1;
+ }
+ return pot;
}
} // namespace tint::utils
diff --git a/src/tint/utils/math_test.cc b/src/tint/utils/math_test.cc
index d6be3f6..515c718 100644
--- a/src/tint/utils/math_test.cc
+++ b/src/tint/utils/math_test.cc
@@ -20,61 +20,61 @@
namespace {
TEST(MathTests, RoundUp) {
- EXPECT_EQ(RoundUp(1, 0), 0);
- EXPECT_EQ(RoundUp(1, 1), 1);
- EXPECT_EQ(RoundUp(1, 2), 2);
+ EXPECT_EQ(RoundUp(1, 0), 0);
+ EXPECT_EQ(RoundUp(1, 1), 1);
+ EXPECT_EQ(RoundUp(1, 2), 2);
- EXPECT_EQ(RoundUp(1, 1), 1);
- EXPECT_EQ(RoundUp(2, 1), 2);
- EXPECT_EQ(RoundUp(3, 1), 3);
- EXPECT_EQ(RoundUp(4, 1), 4);
+ EXPECT_EQ(RoundUp(1, 1), 1);
+ EXPECT_EQ(RoundUp(2, 1), 2);
+ EXPECT_EQ(RoundUp(3, 1), 3);
+ EXPECT_EQ(RoundUp(4, 1), 4);
- EXPECT_EQ(RoundUp(1, 2), 2);
- EXPECT_EQ(RoundUp(2, 2), 2);
- EXPECT_EQ(RoundUp(3, 2), 3);
- EXPECT_EQ(RoundUp(4, 2), 4);
+ EXPECT_EQ(RoundUp(1, 2), 2);
+ EXPECT_EQ(RoundUp(2, 2), 2);
+ EXPECT_EQ(RoundUp(3, 2), 3);
+ EXPECT_EQ(RoundUp(4, 2), 4);
- EXPECT_EQ(RoundUp(1, 3), 3);
- EXPECT_EQ(RoundUp(2, 3), 4);
- EXPECT_EQ(RoundUp(3, 3), 3);
- EXPECT_EQ(RoundUp(4, 3), 4);
+ EXPECT_EQ(RoundUp(1, 3), 3);
+ EXPECT_EQ(RoundUp(2, 3), 4);
+ EXPECT_EQ(RoundUp(3, 3), 3);
+ EXPECT_EQ(RoundUp(4, 3), 4);
- EXPECT_EQ(RoundUp(1, 4), 4);
- EXPECT_EQ(RoundUp(2, 4), 4);
- EXPECT_EQ(RoundUp(3, 4), 6);
- EXPECT_EQ(RoundUp(4, 4), 4);
+ EXPECT_EQ(RoundUp(1, 4), 4);
+ EXPECT_EQ(RoundUp(2, 4), 4);
+ EXPECT_EQ(RoundUp(3, 4), 6);
+ EXPECT_EQ(RoundUp(4, 4), 4);
}
TEST(MathTests, IsPowerOfTwo) {
- EXPECT_EQ(IsPowerOfTwo(1), true);
- EXPECT_EQ(IsPowerOfTwo(2), true);
- EXPECT_EQ(IsPowerOfTwo(3), false);
- EXPECT_EQ(IsPowerOfTwo(4), true);
- EXPECT_EQ(IsPowerOfTwo(5), false);
- EXPECT_EQ(IsPowerOfTwo(6), false);
- EXPECT_EQ(IsPowerOfTwo(7), false);
- EXPECT_EQ(IsPowerOfTwo(8), true);
- EXPECT_EQ(IsPowerOfTwo(9), false);
+ EXPECT_EQ(IsPowerOfTwo(1), true);
+ EXPECT_EQ(IsPowerOfTwo(2), true);
+ EXPECT_EQ(IsPowerOfTwo(3), false);
+ EXPECT_EQ(IsPowerOfTwo(4), true);
+ EXPECT_EQ(IsPowerOfTwo(5), false);
+ EXPECT_EQ(IsPowerOfTwo(6), false);
+ EXPECT_EQ(IsPowerOfTwo(7), false);
+ EXPECT_EQ(IsPowerOfTwo(8), true);
+ EXPECT_EQ(IsPowerOfTwo(9), false);
}
TEST(MathTests, MaxAlignOf) {
- EXPECT_EQ(MaxAlignOf(0u), 1u);
- EXPECT_EQ(MaxAlignOf(1u), 1u);
- EXPECT_EQ(MaxAlignOf(2u), 2u);
- EXPECT_EQ(MaxAlignOf(3u), 1u);
- EXPECT_EQ(MaxAlignOf(4u), 4u);
- EXPECT_EQ(MaxAlignOf(5u), 1u);
- EXPECT_EQ(MaxAlignOf(6u), 2u);
- EXPECT_EQ(MaxAlignOf(7u), 1u);
- EXPECT_EQ(MaxAlignOf(8u), 8u);
- EXPECT_EQ(MaxAlignOf(9u), 1u);
- EXPECT_EQ(MaxAlignOf(10u), 2u);
- EXPECT_EQ(MaxAlignOf(11u), 1u);
- EXPECT_EQ(MaxAlignOf(12u), 4u);
- EXPECT_EQ(MaxAlignOf(13u), 1u);
- EXPECT_EQ(MaxAlignOf(14u), 2u);
- EXPECT_EQ(MaxAlignOf(15u), 1u);
- EXPECT_EQ(MaxAlignOf(16u), 16u);
+ EXPECT_EQ(MaxAlignOf(0u), 1u);
+ EXPECT_EQ(MaxAlignOf(1u), 1u);
+ EXPECT_EQ(MaxAlignOf(2u), 2u);
+ EXPECT_EQ(MaxAlignOf(3u), 1u);
+ EXPECT_EQ(MaxAlignOf(4u), 4u);
+ EXPECT_EQ(MaxAlignOf(5u), 1u);
+ EXPECT_EQ(MaxAlignOf(6u), 2u);
+ EXPECT_EQ(MaxAlignOf(7u), 1u);
+ EXPECT_EQ(MaxAlignOf(8u), 8u);
+ EXPECT_EQ(MaxAlignOf(9u), 1u);
+ EXPECT_EQ(MaxAlignOf(10u), 2u);
+ EXPECT_EQ(MaxAlignOf(11u), 1u);
+ EXPECT_EQ(MaxAlignOf(12u), 4u);
+ EXPECT_EQ(MaxAlignOf(13u), 1u);
+ EXPECT_EQ(MaxAlignOf(14u), 2u);
+ EXPECT_EQ(MaxAlignOf(15u), 1u);
+ EXPECT_EQ(MaxAlignOf(16u), 16u);
}
} // namespace
diff --git a/src/tint/utils/reverse.h b/src/tint/utils/reverse.h
index fb4f237..f28eedd 100644
--- a/src/tint/utils/reverse.h
+++ b/src/tint/utils/reverse.h
@@ -26,18 +26,18 @@
/// See https://en.cppreference.com/w/cpp/language/range-for
template <typename T>
struct ReverseIterable {
- /// The wrapped iterable object.
- T& iterable;
+ /// The wrapped iterable object.
+ T& iterable;
};
template <typename T>
auto begin(ReverseIterable<T> r_it) {
- return std::rbegin(r_it.iterable);
+ return std::rbegin(r_it.iterable);
}
template <typename T>
auto end(ReverseIterable<T> r_it) {
- return std::rend(r_it.iterable);
+ return std::rend(r_it.iterable);
}
} // namespace detail
@@ -54,7 +54,7 @@
/// ```
template <typename T>
detail::ReverseIterable<T> Reverse(T&& iterable) {
- return {iterable};
+ return {iterable};
}
} // namespace tint::utils
diff --git a/src/tint/utils/reverse_test.cc b/src/tint/utils/reverse_test.cc
index b23c799..9bef6de 100644
--- a/src/tint/utils/reverse_test.cc
+++ b/src/tint/utils/reverse_test.cc
@@ -22,12 +22,12 @@
namespace {
TEST(ReverseTest, Vector) {
- std::vector<int> vec{1, 3, 5, 7, 9};
- std::vector<int> rev;
- for (auto v : Reverse(vec)) {
- rev.emplace_back(v);
- }
- ASSERT_THAT(rev, testing::ElementsAre(9, 7, 5, 3, 1));
+ std::vector<int> vec{1, 3, 5, 7, 9};
+ std::vector<int> rev;
+ for (auto v : Reverse(vec)) {
+ rev.emplace_back(v);
+ }
+ ASSERT_THAT(rev, testing::ElementsAre(9, 7, 5, 3, 1));
}
} // namespace
diff --git a/src/tint/utils/scoped_assignment.h b/src/tint/utils/scoped_assignment.h
index fdd787f..6149454 100644
--- a/src/tint/utils/scoped_assignment.h
+++ b/src/tint/utils/scoped_assignment.h
@@ -27,36 +27,36 @@
/// original value is restored.
template <typename T>
class ScopedAssignment {
- public:
- /// Constructor
- /// @param var the variable to temporarily assign a new value to
- /// @param val the value to assign to `ref` for the lifetime of this
- /// ScopedAssignment.
- ScopedAssignment(T& var, T val) : ref_(var) {
- old_value_ = var;
- var = val;
- }
+ public:
+ /// Constructor
+ /// @param var the variable to temporarily assign a new value to
+ /// @param val the value to assign to `ref` for the lifetime of this
+ /// ScopedAssignment.
+ ScopedAssignment(T& var, T val) : ref_(var) {
+ old_value_ = var;
+ var = val;
+ }
- /// Destructor
- /// Restores the original value of the variable.
- ~ScopedAssignment() { ref_ = old_value_; }
+ /// Destructor
+ /// Restores the original value of the variable.
+ ~ScopedAssignment() { ref_ = old_value_; }
- private:
- ScopedAssignment(const ScopedAssignment&) = delete;
- ScopedAssignment& operator=(const ScopedAssignment&) = delete;
+ private:
+ ScopedAssignment(const ScopedAssignment&) = delete;
+ ScopedAssignment& operator=(const ScopedAssignment&) = delete;
- T& ref_;
- T old_value_;
+ T& ref_;
+ T old_value_;
};
} // namespace tint::utils
/// TINT_SCOPED_ASSIGNMENT(var, val) assigns `val` to `var`, and automatically
/// restores the original value of `var` when exiting the current lexical scope.
-#define TINT_SCOPED_ASSIGNMENT(var, val) \
- ::tint::utils::ScopedAssignment<std::remove_reference_t<decltype(var)>> \
- TINT_CONCAT(tint_scoped_assignment_, __COUNTER__) { \
- var, val \
- }
+#define TINT_SCOPED_ASSIGNMENT(var, val) \
+ ::tint::utils::ScopedAssignment<std::remove_reference_t<decltype(var)>> TINT_CONCAT( \
+ tint_scoped_assignment_, __COUNTER__) { \
+ var, val \
+ }
#endif // SRC_TINT_UTILS_SCOPED_ASSIGNMENT_H_
diff --git a/src/tint/utils/scoped_assignment_test.cc b/src/tint/utils/scoped_assignment_test.cc
index 3055afe..3c0c548 100644
--- a/src/tint/utils/scoped_assignment_test.cc
+++ b/src/tint/utils/scoped_assignment_test.cc
@@ -20,25 +20,25 @@
namespace {
TEST(ScopedAssignmentTest, Scopes) {
- int i = 0;
- EXPECT_EQ(i, 0);
- {
+ int i = 0;
EXPECT_EQ(i, 0);
- TINT_SCOPED_ASSIGNMENT(i, 1);
- EXPECT_EQ(i, 1);
{
- EXPECT_EQ(i, 1);
- TINT_SCOPED_ASSIGNMENT(i, 2);
- EXPECT_EQ(i, 2);
+ EXPECT_EQ(i, 0);
+ TINT_SCOPED_ASSIGNMENT(i, 1);
+ EXPECT_EQ(i, 1);
+ {
+ EXPECT_EQ(i, 1);
+ TINT_SCOPED_ASSIGNMENT(i, 2);
+ EXPECT_EQ(i, 2);
+ }
+ {
+ EXPECT_EQ(i, 1);
+ TINT_SCOPED_ASSIGNMENT(i, 3);
+ EXPECT_EQ(i, 3);
+ }
+ EXPECT_EQ(i, 1);
}
- {
- EXPECT_EQ(i, 1);
- TINT_SCOPED_ASSIGNMENT(i, 3);
- EXPECT_EQ(i, 3);
- }
- EXPECT_EQ(i, 1);
- }
- EXPECT_EQ(i, 0);
+ EXPECT_EQ(i, 0);
}
} // namespace
diff --git a/src/tint/utils/string.h b/src/tint/utils/string.h
index 011e326..a11e44e 100644
--- a/src/tint/utils/string.h
+++ b/src/tint/utils/string.h
@@ -26,12 +26,12 @@
inline std::string ReplaceAll(std::string str,
const std::string& substr,
const std::string& replacement) {
- size_t pos = 0;
- while ((pos = str.find(substr, pos)) != std::string::npos) {
- str.replace(pos, substr.length(), replacement);
- pos += replacement.length();
- }
- return str;
+ size_t pos = 0;
+ while ((pos = str.find(substr, pos)) != std::string::npos) {
+ str.replace(pos, substr.length(), replacement);
+ pos += replacement.length();
+ }
+ return str;
}
} // namespace tint::utils
diff --git a/src/tint/utils/string_test.cc b/src/tint/utils/string_test.cc
index f394ed7..0d3e14f 100644
--- a/src/tint/utils/string_test.cc
+++ b/src/tint/utils/string_test.cc
@@ -20,16 +20,16 @@
namespace {
TEST(StringTest, ReplaceAll) {
- ASSERT_EQ("xybbcc", ReplaceAll("aabbcc", "aa", "xy"));
- ASSERT_EQ("aaxycc", ReplaceAll("aabbcc", "bb", "xy"));
- ASSERT_EQ("aabbxy", ReplaceAll("aabbcc", "cc", "xy"));
- ASSERT_EQ("xyxybbcc", ReplaceAll("aabbcc", "a", "xy"));
- ASSERT_EQ("aaxyxycc", ReplaceAll("aabbcc", "b", "xy"));
- ASSERT_EQ("aabbxyxy", ReplaceAll("aabbcc", "c", "xy"));
- // Replacement string includes the searched-for string.
- // This proves that the algorithm needs to advance 'pos'
- // past the replacement.
- ASSERT_EQ("aabxybbxybcc", ReplaceAll("aabbcc", "b", "bxyb"));
+ ASSERT_EQ("xybbcc", ReplaceAll("aabbcc", "aa", "xy"));
+ ASSERT_EQ("aaxycc", ReplaceAll("aabbcc", "bb", "xy"));
+ ASSERT_EQ("aabbxy", ReplaceAll("aabbcc", "cc", "xy"));
+ ASSERT_EQ("xyxybbcc", ReplaceAll("aabbcc", "a", "xy"));
+ ASSERT_EQ("aaxyxycc", ReplaceAll("aabbcc", "b", "xy"));
+ ASSERT_EQ("aabbxyxy", ReplaceAll("aabbcc", "c", "xy"));
+ // Replacement string includes the searched-for string.
+ // This proves that the algorithm needs to advance 'pos'
+ // past the replacement.
+ ASSERT_EQ("aabxybbxybcc", ReplaceAll("aabbcc", "b", "bxyb"));
}
} // namespace
diff --git a/src/tint/utils/to_const_ptr_vec.h b/src/tint/utils/to_const_ptr_vec.h
index a46b3ba..02cc984 100644
--- a/src/tint/utils/to_const_ptr_vec.h
+++ b/src/tint/utils/to_const_ptr_vec.h
@@ -24,12 +24,12 @@
/// @returns a vector of `const T*` with the content of `in`.
template <typename T>
std::vector<const T*> ToConstPtrVec(const std::vector<T*>& in) {
- std::vector<const T*> out;
- out.reserve(in.size());
- for (auto* ptr : in) {
- out.emplace_back(ptr);
- }
- return out;
+ std::vector<const T*> out;
+ out.reserve(in.size());
+ for (auto* ptr : in) {
+ out.emplace_back(ptr);
+ }
+ return out;
}
} // namespace tint::utils
diff --git a/src/tint/utils/transform.h b/src/tint/utils/transform.h
index 29a9740..2cd9481 100644
--- a/src/tint/utils/transform.h
+++ b/src/tint/utils/transform.h
@@ -32,11 +32,11 @@
template <typename IN, typename TRANSFORMER>
auto Transform(const std::vector<IN>& in, TRANSFORMER&& transform)
-> std::vector<decltype(transform(in[0]))> {
- std::vector<decltype(transform(in[0]))> result(in.size());
- for (size_t i = 0; i < result.size(); ++i) {
- result[i] = transform(in[i]);
- }
- return result;
+ std::vector<decltype(transform(in[0]))> result(in.size());
+ for (size_t i = 0; i < result.size(); ++i) {
+ result[i] = transform(in[i]);
+ }
+ return result;
}
/// Transform performs an element-wise transformation of a vector.
@@ -48,11 +48,11 @@
template <typename IN, typename TRANSFORMER>
auto Transform(const std::vector<IN>& in, TRANSFORMER&& transform)
-> std::vector<decltype(transform(in[0], 1u))> {
- std::vector<decltype(transform(in[0], 1u))> result(in.size());
- for (size_t i = 0; i < result.size(); ++i) {
- result[i] = transform(in[i], i);
- }
- return result;
+ std::vector<decltype(transform(in[0], 1u))> result(in.size());
+ for (size_t i = 0; i < result.size(); ++i) {
+ result[i] = transform(in[i], i);
+ }
+ return result;
}
} // namespace tint::utils
diff --git a/src/tint/utils/transform_test.cc b/src/tint/utils/transform_test.cc
index e668824..af8b832 100644
--- a/src/tint/utils/transform_test.cc
+++ b/src/tint/utils/transform_test.cc
@@ -19,73 +19,72 @@
#include "gmock/gmock.h"
-#define CHECK_ELEMENT_TYPE(vector, expected) \
- static_assert(std::is_same<decltype(vector)::value_type, expected>::value, \
- "unexpected result vector element type")
+#define CHECK_ELEMENT_TYPE(vector, expected) \
+ static_assert(std::is_same<decltype(vector)::value_type, expected>::value, \
+ "unexpected result vector element type")
namespace tint::utils {
namespace {
TEST(TransformTest, Empty) {
- const std::vector<int> empty{};
- {
- auto transformed = Transform(empty, [](int) -> int {
- [] { FAIL() << "Transform should not be called for empty vector"; }();
- return 0;
- });
- CHECK_ELEMENT_TYPE(transformed, int);
- EXPECT_EQ(transformed.size(), 0u);
- }
- {
- auto transformed = Transform(empty, [](int, size_t) -> int {
- [] { FAIL() << "Transform should not be called for empty vector"; }();
- return 0;
- });
- CHECK_ELEMENT_TYPE(transformed, int);
- EXPECT_EQ(transformed.size(), 0u);
- }
+ const std::vector<int> empty{};
+ {
+ auto transformed = Transform(empty, [](int) -> int {
+ [] { FAIL() << "Transform should not be called for empty vector"; }();
+ return 0;
+ });
+ CHECK_ELEMENT_TYPE(transformed, int);
+ EXPECT_EQ(transformed.size(), 0u);
+ }
+ {
+ auto transformed = Transform(empty, [](int, size_t) -> int {
+ [] { FAIL() << "Transform should not be called for empty vector"; }();
+ return 0;
+ });
+ CHECK_ELEMENT_TYPE(transformed, int);
+ EXPECT_EQ(transformed.size(), 0u);
+ }
}
TEST(TransformTest, Identity) {
- const std::vector<int> input{1, 2, 3, 4};
- {
- auto transformed = Transform(input, [](int i) { return i; });
- CHECK_ELEMENT_TYPE(transformed, int);
- EXPECT_THAT(transformed, testing::ElementsAre(1, 2, 3, 4));
- }
- {
- auto transformed = Transform(input, [](int i, size_t) { return i; });
- CHECK_ELEMENT_TYPE(transformed, int);
- EXPECT_THAT(transformed, testing::ElementsAre(1, 2, 3, 4));
- }
+ const std::vector<int> input{1, 2, 3, 4};
+ {
+ auto transformed = Transform(input, [](int i) { return i; });
+ CHECK_ELEMENT_TYPE(transformed, int);
+ EXPECT_THAT(transformed, testing::ElementsAre(1, 2, 3, 4));
+ }
+ {
+ auto transformed = Transform(input, [](int i, size_t) { return i; });
+ CHECK_ELEMENT_TYPE(transformed, int);
+ EXPECT_THAT(transformed, testing::ElementsAre(1, 2, 3, 4));
+ }
}
TEST(TransformTest, Index) {
- const std::vector<int> input{10, 20, 30, 40};
- {
- auto transformed = Transform(input, [](int, size_t idx) { return idx; });
- CHECK_ELEMENT_TYPE(transformed, size_t);
- EXPECT_THAT(transformed, testing::ElementsAre(0u, 1u, 2u, 3u));
- }
+ const std::vector<int> input{10, 20, 30, 40};
+ {
+ auto transformed = Transform(input, [](int, size_t idx) { return idx; });
+ CHECK_ELEMENT_TYPE(transformed, size_t);
+ EXPECT_THAT(transformed, testing::ElementsAre(0u, 1u, 2u, 3u));
+ }
}
TEST(TransformTest, TransformSameType) {
- const std::vector<int> input{1, 2, 3, 4};
- {
- auto transformed = Transform(input, [](int i) { return i * 10; });
- CHECK_ELEMENT_TYPE(transformed, int);
- EXPECT_THAT(transformed, testing::ElementsAre(10, 20, 30, 40));
- }
+ const std::vector<int> input{1, 2, 3, 4};
+ {
+ auto transformed = Transform(input, [](int i) { return i * 10; });
+ CHECK_ELEMENT_TYPE(transformed, int);
+ EXPECT_THAT(transformed, testing::ElementsAre(10, 20, 30, 40));
+ }
}
TEST(TransformTest, TransformDifferentType) {
- const std::vector<int> input{1, 2, 3, 4};
- {
- auto transformed =
- Transform(input, [](int i) { return std::to_string(i); });
- CHECK_ELEMENT_TYPE(transformed, std::string);
- EXPECT_THAT(transformed, testing::ElementsAre("1", "2", "3", "4"));
- }
+ const std::vector<int> input{1, 2, 3, 4};
+ {
+ auto transformed = Transform(input, [](int i) { return std::to_string(i); });
+ CHECK_ELEMENT_TYPE(transformed, std::string);
+ EXPECT_THAT(transformed, testing::ElementsAre("1", "2", "3", "4"));
+ }
}
} // namespace
diff --git a/src/tint/utils/unique_allocator.h b/src/tint/utils/unique_allocator.h
index 69242fb..628bc79 100644
--- a/src/tint/utils/unique_allocator.h
+++ b/src/tint/utils/unique_allocator.h
@@ -25,58 +25,56 @@
/// UniqueAllocator is used to allocate unique instances of the template type
/// `T`.
-template <typename T,
- typename HASH = std::hash<T>,
- typename EQUAL = std::equal_to<T>>
+template <typename T, typename HASH = std::hash<T>, typename EQUAL = std::equal_to<T>>
class UniqueAllocator {
- public:
- /// @param args the arguments used to construct the object.
- /// @return a pointer to an instance of `T` with the provided arguments.
- /// If an existing instance of `T` has been constructed, then the same
- /// pointer is returned.
- template <typename TYPE = T, typename... ARGS>
- TYPE* Get(ARGS&&... args) {
- // Create a temporary T instance on the stack so that we can hash it, and
- // use it for equality lookup for the std::unordered_set. If the item is not
- // found in the set, then we create the persisted instance with the
- // allocator.
- TYPE key{args...};
- auto hash = HASH{}(key);
- auto it = items.find(Entry{hash, &key});
- if (it != items.end()) {
- return static_cast<TYPE*>(it->ptr);
+ public:
+ /// @param args the arguments used to construct the object.
+ /// @return a pointer to an instance of `T` with the provided arguments.
+ /// If an existing instance of `T` has been constructed, then the same
+ /// pointer is returned.
+ template <typename TYPE = T, typename... ARGS>
+ TYPE* Get(ARGS&&... args) {
+ // Create a temporary T instance on the stack so that we can hash it, and
+ // use it for equality lookup for the std::unordered_set. If the item is not
+ // found in the set, then we create the persisted instance with the
+ // allocator.
+ TYPE key{args...};
+ auto hash = HASH{}(key);
+ auto it = items.find(Entry{hash, &key});
+ if (it != items.end()) {
+ return static_cast<TYPE*>(it->ptr);
+ }
+ auto* ptr = allocator.template Create<TYPE>(std::forward<ARGS>(args)...);
+ items.emplace_hint(it, Entry{hash, ptr});
+ return ptr;
}
- auto* ptr = allocator.template Create<TYPE>(std::forward<ARGS>(args)...);
- items.emplace_hint(it, Entry{hash, ptr});
- return ptr;
- }
- protected:
- /// Entry is used as the entry to the unordered_set
- struct Entry {
- /// The pre-calculated hash of the entry
- size_t hash;
- /// Tge pointer to the unique object
- T* ptr;
- };
- /// Comparator is the hashing and equality function used by the unordered_set
- struct Comparator {
- /// Hashing function
- /// @param e the entry
- /// @returns the hash of the entry
- size_t operator()(Entry e) const { return e.hash; }
+ protected:
+ /// Entry is used as the entry to the unordered_set
+ struct Entry {
+ /// The pre-calculated hash of the entry
+ size_t hash;
+ /// Tge pointer to the unique object
+ T* ptr;
+ };
+ /// Comparator is the hashing and equality function used by the unordered_set
+ struct Comparator {
+ /// Hashing function
+ /// @param e the entry
+ /// @returns the hash of the entry
+ size_t operator()(Entry e) const { return e.hash; }
- /// Equality function
- /// @param a the first entry to compare
- /// @param b the second entry to compare
- /// @returns true if the two entries are equal
- bool operator()(Entry a, Entry b) const { return EQUAL{}(*a.ptr, *b.ptr); }
- };
+ /// Equality function
+ /// @param a the first entry to compare
+ /// @param b the second entry to compare
+ /// @returns true if the two entries are equal
+ bool operator()(Entry a, Entry b) const { return EQUAL{}(*a.ptr, *b.ptr); }
+ };
- /// The block allocator used to allocate the unique objects
- BlockAllocator<T> allocator;
- /// The unordered_set of unique item entries
- std::unordered_set<Entry, Comparator, Comparator> items;
+ /// The block allocator used to allocate the unique objects
+ BlockAllocator<T> allocator;
+ /// The unordered_set of unique item entries
+ std::unordered_set<Entry, Comparator, Comparator> items;
};
} // namespace tint::utils
diff --git a/src/tint/utils/unique_allocator_test.cc b/src/tint/utils/unique_allocator_test.cc
index d8d62df..b618734 100644
--- a/src/tint/utils/unique_allocator_test.cc
+++ b/src/tint/utils/unique_allocator_test.cc
@@ -22,30 +22,30 @@
namespace {
TEST(UniqueAllocator, Int) {
- UniqueAllocator<int> a;
- EXPECT_NE(a.Get(0), a.Get(1));
- EXPECT_NE(a.Get(1), a.Get(2));
- EXPECT_EQ(a.Get(0), a.Get(0));
- EXPECT_EQ(a.Get(1), a.Get(1));
- EXPECT_EQ(a.Get(2), a.Get(2));
+ UniqueAllocator<int> a;
+ EXPECT_NE(a.Get(0), a.Get(1));
+ EXPECT_NE(a.Get(1), a.Get(2));
+ EXPECT_EQ(a.Get(0), a.Get(0));
+ EXPECT_EQ(a.Get(1), a.Get(1));
+ EXPECT_EQ(a.Get(2), a.Get(2));
}
TEST(UniqueAllocator, Float) {
- UniqueAllocator<float> a;
- EXPECT_NE(a.Get(0.1f), a.Get(1.1f));
- EXPECT_NE(a.Get(1.1f), a.Get(2.1f));
- EXPECT_EQ(a.Get(0.1f), a.Get(0.1f));
- EXPECT_EQ(a.Get(1.1f), a.Get(1.1f));
- EXPECT_EQ(a.Get(2.1f), a.Get(2.1f));
+ UniqueAllocator<float> a;
+ EXPECT_NE(a.Get(0.1f), a.Get(1.1f));
+ EXPECT_NE(a.Get(1.1f), a.Get(2.1f));
+ EXPECT_EQ(a.Get(0.1f), a.Get(0.1f));
+ EXPECT_EQ(a.Get(1.1f), a.Get(1.1f));
+ EXPECT_EQ(a.Get(2.1f), a.Get(2.1f));
}
TEST(UniqueAllocator, String) {
- UniqueAllocator<std::string> a;
- EXPECT_NE(a.Get("x"), a.Get("y"));
- EXPECT_NE(a.Get("z"), a.Get("w"));
- EXPECT_EQ(a.Get("x"), a.Get("x"));
- EXPECT_EQ(a.Get("y"), a.Get("y"));
- EXPECT_EQ(a.Get("z"), a.Get("z"));
+ UniqueAllocator<std::string> a;
+ EXPECT_NE(a.Get("x"), a.Get("y"));
+ EXPECT_NE(a.Get("z"), a.Get("w"));
+ EXPECT_EQ(a.Get("x"), a.Get("x"));
+ EXPECT_EQ(a.Get("y"), a.Get("y"));
+ EXPECT_EQ(a.Get("z"), a.Get("z"));
}
} // namespace
diff --git a/src/tint/utils/unique_vector.h b/src/tint/utils/unique_vector.h
index 32d593e..96d9cbf 100644
--- a/src/tint/utils/unique_vector.h
+++ b/src/tint/utils/unique_vector.h
@@ -25,85 +25,83 @@
/// UniqueVector is an ordered container that only contains unique items.
/// Attempting to add a duplicate is a no-op.
-template <typename T,
- typename HASH = std::hash<T>,
- typename EQUAL = std::equal_to<T>>
+template <typename T, typename HASH = std::hash<T>, typename EQUAL = std::equal_to<T>>
struct UniqueVector {
- /// The iterator returned by begin() and end()
- using ConstIterator = typename std::vector<T>::const_iterator;
- /// The iterator returned by rbegin() and rend()
- using ConstReverseIterator = typename std::vector<T>::const_reverse_iterator;
+ /// The iterator returned by begin() and end()
+ using ConstIterator = typename std::vector<T>::const_iterator;
+ /// The iterator returned by rbegin() and rend()
+ using ConstReverseIterator = typename std::vector<T>::const_reverse_iterator;
- /// Constructor
- UniqueVector() = default;
+ /// Constructor
+ UniqueVector() = default;
- /// Constructor
- /// @param v the vector to construct this UniqueVector with. Duplicate
- /// elements will be removed.
- explicit UniqueVector(std::vector<T>&& v) {
- for (auto& el : v) {
- add(el);
+ /// Constructor
+ /// @param v the vector to construct this UniqueVector with. Duplicate
+ /// elements will be removed.
+ explicit UniqueVector(std::vector<T>&& v) {
+ for (auto& el : v) {
+ add(el);
+ }
}
- }
- /// add appends the item to the end of the vector, if the vector does not
- /// already contain the given item.
- /// @param item the item to append to the end of the vector
- /// @returns true if the item was added, otherwise false.
- bool add(const T& item) {
- if (set.count(item) == 0) {
- vector.emplace_back(item);
- set.emplace(item);
- return true;
+ /// add appends the item to the end of the vector, if the vector does not
+ /// already contain the given item.
+ /// @param item the item to append to the end of the vector
+ /// @returns true if the item was added, otherwise false.
+ bool add(const T& item) {
+ if (set.count(item) == 0) {
+ vector.emplace_back(item);
+ set.emplace(item);
+ return true;
+ }
+ return false;
}
- return false;
- }
- /// @returns true if the vector contains `item`
- /// @param item the item
- bool contains(const T& item) const { return set.count(item); }
+ /// @returns true if the vector contains `item`
+ /// @param item the item
+ bool contains(const T& item) const { return set.count(item); }
- /// @param i the index of the element to retrieve
- /// @returns the element at the index `i`
- T& operator[](size_t i) { return vector[i]; }
+ /// @param i the index of the element to retrieve
+ /// @returns the element at the index `i`
+ T& operator[](size_t i) { return vector[i]; }
- /// @param i the index of the element to retrieve
- /// @returns the element at the index `i`
- const T& operator[](size_t i) const { return vector[i]; }
+ /// @param i the index of the element to retrieve
+ /// @returns the element at the index `i`
+ const T& operator[](size_t i) const { return vector[i]; }
- /// @returns true if the vector is empty
- bool empty() const { return vector.empty(); }
+ /// @returns true if the vector is empty
+ bool empty() const { return vector.empty(); }
- /// @returns the number of items in the vector
- size_t size() const { return vector.size(); }
+ /// @returns the number of items in the vector
+ size_t size() const { return vector.size(); }
- /// @returns an iterator to the beginning of the vector
- ConstIterator begin() const { return vector.begin(); }
+ /// @returns an iterator to the beginning of the vector
+ ConstIterator begin() const { return vector.begin(); }
- /// @returns an iterator to the end of the vector
- ConstIterator end() const { return vector.end(); }
+ /// @returns an iterator to the end of the vector
+ ConstIterator end() const { return vector.end(); }
- /// @returns an iterator to the beginning of the reversed vector
- ConstReverseIterator rbegin() const { return vector.rbegin(); }
+ /// @returns an iterator to the beginning of the reversed vector
+ ConstReverseIterator rbegin() const { return vector.rbegin(); }
- /// @returns an iterator to the end of the reversed vector
- ConstReverseIterator rend() const { return vector.rend(); }
+ /// @returns an iterator to the end of the reversed vector
+ ConstReverseIterator rend() const { return vector.rend(); }
- /// @returns a const reference to the internal vector
- operator const std::vector<T>&() const { return vector; }
+ /// @returns a const reference to the internal vector
+ operator const std::vector<T>&() const { return vector; }
- /// Removes the last element from the vector
- /// @returns the popped element
- T pop_back() {
- auto el = std::move(vector.back());
- set.erase(el);
- vector.pop_back();
- return el;
- }
+ /// Removes the last element from the vector
+ /// @returns the popped element
+ T pop_back() {
+ auto el = std::move(vector.back());
+ set.erase(el);
+ vector.pop_back();
+ return el;
+ }
- private:
- std::vector<T> vector;
- std::unordered_set<T, HASH, EQUAL> set;
+ private:
+ std::vector<T> vector;
+ std::unordered_set<T, HASH, EQUAL> set;
};
} // namespace tint::utils
diff --git a/src/tint/utils/unique_vector_test.cc b/src/tint/utils/unique_vector_test.cc
index c2c47a4..7d586e9 100644
--- a/src/tint/utils/unique_vector_test.cc
+++ b/src/tint/utils/unique_vector_test.cc
@@ -21,122 +21,122 @@
namespace {
TEST(UniqueVectorTest, Empty) {
- UniqueVector<int> unique_vec;
- EXPECT_EQ(unique_vec.size(), 0u);
- EXPECT_EQ(unique_vec.empty(), true);
- EXPECT_EQ(unique_vec.begin(), unique_vec.end());
+ UniqueVector<int> unique_vec;
+ EXPECT_EQ(unique_vec.size(), 0u);
+ EXPECT_EQ(unique_vec.empty(), true);
+ EXPECT_EQ(unique_vec.begin(), unique_vec.end());
}
TEST(UniqueVectorTest, MoveConstructor) {
- UniqueVector<int> unique_vec(std::vector<int>{0, 3, 2, 1, 2});
- EXPECT_EQ(unique_vec.size(), 4u);
- EXPECT_EQ(unique_vec.empty(), false);
- EXPECT_EQ(unique_vec[0], 0);
- EXPECT_EQ(unique_vec[1], 3);
- EXPECT_EQ(unique_vec[2], 2);
- EXPECT_EQ(unique_vec[3], 1);
+ UniqueVector<int> unique_vec(std::vector<int>{0, 3, 2, 1, 2});
+ EXPECT_EQ(unique_vec.size(), 4u);
+ EXPECT_EQ(unique_vec.empty(), false);
+ EXPECT_EQ(unique_vec[0], 0);
+ EXPECT_EQ(unique_vec[1], 3);
+ EXPECT_EQ(unique_vec[2], 2);
+ EXPECT_EQ(unique_vec[3], 1);
}
TEST(UniqueVectorTest, AddUnique) {
- UniqueVector<int> unique_vec;
- unique_vec.add(0);
- unique_vec.add(1);
- unique_vec.add(2);
- EXPECT_EQ(unique_vec.size(), 3u);
- EXPECT_EQ(unique_vec.empty(), false);
- int i = 0;
- for (auto n : unique_vec) {
- EXPECT_EQ(n, i);
- i++;
- }
- for (auto n : Reverse(unique_vec)) {
- i--;
- EXPECT_EQ(n, i);
- }
- EXPECT_EQ(unique_vec[0], 0);
- EXPECT_EQ(unique_vec[1], 1);
- EXPECT_EQ(unique_vec[2], 2);
+ UniqueVector<int> unique_vec;
+ unique_vec.add(0);
+ unique_vec.add(1);
+ unique_vec.add(2);
+ EXPECT_EQ(unique_vec.size(), 3u);
+ EXPECT_EQ(unique_vec.empty(), false);
+ int i = 0;
+ for (auto n : unique_vec) {
+ EXPECT_EQ(n, i);
+ i++;
+ }
+ for (auto n : Reverse(unique_vec)) {
+ i--;
+ EXPECT_EQ(n, i);
+ }
+ EXPECT_EQ(unique_vec[0], 0);
+ EXPECT_EQ(unique_vec[1], 1);
+ EXPECT_EQ(unique_vec[2], 2);
}
TEST(UniqueVectorTest, AddDuplicates) {
- UniqueVector<int> unique_vec;
- unique_vec.add(0);
- unique_vec.add(0);
- unique_vec.add(0);
- unique_vec.add(1);
- unique_vec.add(1);
- unique_vec.add(2);
- EXPECT_EQ(unique_vec.size(), 3u);
- EXPECT_EQ(unique_vec.empty(), false);
- int i = 0;
- for (auto n : unique_vec) {
- EXPECT_EQ(n, i);
- i++;
- }
- for (auto n : Reverse(unique_vec)) {
- i--;
- EXPECT_EQ(n, i);
- }
- EXPECT_EQ(unique_vec[0], 0);
- EXPECT_EQ(unique_vec[1], 1);
- EXPECT_EQ(unique_vec[2], 2);
+ UniqueVector<int> unique_vec;
+ unique_vec.add(0);
+ unique_vec.add(0);
+ unique_vec.add(0);
+ unique_vec.add(1);
+ unique_vec.add(1);
+ unique_vec.add(2);
+ EXPECT_EQ(unique_vec.size(), 3u);
+ EXPECT_EQ(unique_vec.empty(), false);
+ int i = 0;
+ for (auto n : unique_vec) {
+ EXPECT_EQ(n, i);
+ i++;
+ }
+ for (auto n : Reverse(unique_vec)) {
+ i--;
+ EXPECT_EQ(n, i);
+ }
+ EXPECT_EQ(unique_vec[0], 0);
+ EXPECT_EQ(unique_vec[1], 1);
+ EXPECT_EQ(unique_vec[2], 2);
}
TEST(UniqueVectorTest, AsVector) {
- UniqueVector<int> unique_vec;
- unique_vec.add(0);
- unique_vec.add(0);
- unique_vec.add(0);
- unique_vec.add(1);
- unique_vec.add(1);
- unique_vec.add(2);
+ UniqueVector<int> unique_vec;
+ unique_vec.add(0);
+ unique_vec.add(0);
+ unique_vec.add(0);
+ unique_vec.add(1);
+ unique_vec.add(1);
+ unique_vec.add(2);
- const std::vector<int>& vec = unique_vec;
- EXPECT_EQ(vec.size(), 3u);
- EXPECT_EQ(unique_vec.empty(), false);
- int i = 0;
- for (auto n : vec) {
- EXPECT_EQ(n, i);
- i++;
- }
- for (auto n : Reverse(unique_vec)) {
- i--;
- EXPECT_EQ(n, i);
- }
+ const std::vector<int>& vec = unique_vec;
+ EXPECT_EQ(vec.size(), 3u);
+ EXPECT_EQ(unique_vec.empty(), false);
+ int i = 0;
+ for (auto n : vec) {
+ EXPECT_EQ(n, i);
+ i++;
+ }
+ for (auto n : Reverse(unique_vec)) {
+ i--;
+ EXPECT_EQ(n, i);
+ }
}
TEST(UniqueVectorTest, PopBack) {
- UniqueVector<int> unique_vec;
- unique_vec.add(0);
- unique_vec.add(2);
- unique_vec.add(1);
+ UniqueVector<int> unique_vec;
+ unique_vec.add(0);
+ unique_vec.add(2);
+ unique_vec.add(1);
- EXPECT_EQ(unique_vec.pop_back(), 1);
- EXPECT_EQ(unique_vec.size(), 2u);
- EXPECT_EQ(unique_vec.empty(), false);
- EXPECT_EQ(unique_vec[0], 0);
- EXPECT_EQ(unique_vec[1], 2);
+ EXPECT_EQ(unique_vec.pop_back(), 1);
+ EXPECT_EQ(unique_vec.size(), 2u);
+ EXPECT_EQ(unique_vec.empty(), false);
+ EXPECT_EQ(unique_vec[0], 0);
+ EXPECT_EQ(unique_vec[1], 2);
- EXPECT_EQ(unique_vec.pop_back(), 2);
- EXPECT_EQ(unique_vec.size(), 1u);
- EXPECT_EQ(unique_vec.empty(), false);
- EXPECT_EQ(unique_vec[0], 0);
+ EXPECT_EQ(unique_vec.pop_back(), 2);
+ EXPECT_EQ(unique_vec.size(), 1u);
+ EXPECT_EQ(unique_vec.empty(), false);
+ EXPECT_EQ(unique_vec[0], 0);
- unique_vec.add(1);
+ unique_vec.add(1);
- EXPECT_EQ(unique_vec.size(), 2u);
- EXPECT_EQ(unique_vec.empty(), false);
- EXPECT_EQ(unique_vec[0], 0);
- EXPECT_EQ(unique_vec[1], 1);
+ EXPECT_EQ(unique_vec.size(), 2u);
+ EXPECT_EQ(unique_vec.empty(), false);
+ EXPECT_EQ(unique_vec[0], 0);
+ EXPECT_EQ(unique_vec[1], 1);
- EXPECT_EQ(unique_vec.pop_back(), 1);
- EXPECT_EQ(unique_vec.size(), 1u);
- EXPECT_EQ(unique_vec.empty(), false);
- EXPECT_EQ(unique_vec[0], 0);
+ EXPECT_EQ(unique_vec.pop_back(), 1);
+ EXPECT_EQ(unique_vec.size(), 1u);
+ EXPECT_EQ(unique_vec.empty(), false);
+ EXPECT_EQ(unique_vec[0], 0);
- EXPECT_EQ(unique_vec.pop_back(), 0);
- EXPECT_EQ(unique_vec.size(), 0u);
- EXPECT_EQ(unique_vec.empty(), true);
+ EXPECT_EQ(unique_vec.pop_back(), 0);
+ EXPECT_EQ(unique_vec.size(), 0u);
+ EXPECT_EQ(unique_vec.empty(), true);
}
} // namespace