Add a Python-like Range iterator.
This is to help iterate over ranges of typed integers.
Bug: dawn:2222
Change-Id: I63c827cf98e8cf07a8bc2be3bc2d01c6799e97af
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/162503
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Austin Eng <enga@chromium.org>
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Loko Kung <lokokung@google.com>
diff --git a/src/dawn/common/BUILD.gn b/src/dawn/common/BUILD.gn
index f175c4e..6d9d917 100644
--- a/src/dawn/common/BUILD.gn
+++ b/src/dawn/common/BUILD.gn
@@ -274,6 +274,7 @@
"PlacementAllocated.h",
"Platform.h",
"Preprocessor.h",
+ "Range.h",
"Ref.h",
"RefBase.h",
"RefCounted.cpp",
diff --git a/src/dawn/common/CMakeLists.txt b/src/dawn/common/CMakeLists.txt
index 4d4a878..f676382 100644
--- a/src/dawn/common/CMakeLists.txt
+++ b/src/dawn/common/CMakeLists.txt
@@ -77,6 +77,7 @@
"PlacementAllocated.h"
"Platform.h"
"Preprocessor.h"
+ "Range.h"
"Ref.h"
"RefBase.h"
"RefCounted.cpp"
diff --git a/src/dawn/common/Range.h b/src/dawn/common/Range.h
new file mode 100644
index 0000000..8ab2cf4
--- /dev/null
+++ b/src/dawn/common/Range.h
@@ -0,0 +1,85 @@
+// Copyright 2023 The Dawn & Tint Authors
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this
+// list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// 3. Neither the name of the copyright holder nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef SRC_DAWN_COMMON_RANGE_H_
+#define SRC_DAWN_COMMON_RANGE_H_
+
+#include <type_traits>
+#include <utility>
+
+namespace dawn {
+
+// An iterator over a range of numbers. Simplified version of Python's range() iterator that works
+// with any integer type (including ityp).
+//
+// Iterates over [0, end) in order:
+//
+// for (auto i : Range(end)) { ... }
+//
+// Iterates over [start, end) in order:
+//
+// for (auto i = Range(start, end)) { ... }
+template <typename Integer>
+class BeginEndRange {
+ public:
+ BeginEndRange(Integer begin, Integer end) : mBegin(begin), mEnd(end) {}
+
+ class Iterator final {
+ public:
+ explicit Iterator(Integer value) : mValue(value) {}
+ bool operator==(const Iterator& other) const { return other.mValue == mValue; }
+ bool operator!=(const Iterator& other) const { return !(*this == other); }
+ Iterator& operator++() {
+ mValue++;
+ return *this;
+ }
+ Integer operator*() const { return mValue; }
+
+ private:
+ Integer mValue;
+ };
+
+ Iterator begin() const { return Iterator(mBegin); }
+ Iterator end() const { return Iterator(mEnd); }
+
+ private:
+ Integer mBegin;
+ Integer mEnd;
+};
+
+template <typename Integer>
+BeginEndRange<Integer> Range(Integer end) {
+ return {Integer{}, end};
+}
+template <typename Integer>
+BeginEndRange<Integer> Range(Integer begin, Integer end) {
+ return {begin, end};
+}
+
+} // namespace dawn
+
+#endif // SRC_DAWN_COMMON_RANGE_H_
diff --git a/src/dawn/tests/BUILD.gn b/src/dawn/tests/BUILD.gn
index de77a43..15b5c6d 100644
--- a/src/dawn/tests/BUILD.gn
+++ b/src/dawn/tests/BUILD.gn
@@ -325,6 +325,7 @@
"unittests/PerStageTests.cpp",
"unittests/PerThreadProcTests.cpp",
"unittests/PlacementAllocatedTests.cpp",
+ "unittests/RangeTests.cpp",
"unittests/RefBaseTests.cpp",
"unittests/RefCountedTests.cpp",
"unittests/ResultTests.cpp",
diff --git a/src/dawn/tests/unittests/RangeTests.cpp b/src/dawn/tests/unittests/RangeTests.cpp
new file mode 100644
index 0000000..0f0dd9d
--- /dev/null
+++ b/src/dawn/tests/unittests/RangeTests.cpp
@@ -0,0 +1,89 @@
+// Copyright 2023 The Dawn & Tint Authors
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this
+// list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// 3. Neither the name of the copyright holder nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "dawn/common/Compiler.h"
+#include "dawn/common/Range.h"
+#include "dawn/common/TypedInteger.h"
+#include "gtest/gtest.h"
+
+namespace dawn {
+namespace {
+
+// Test that iterating an empty range doesn't iterate at all.
+TEST(RangeTests, Empty) {
+ for (auto i : Range(0)) {
+ // Silence a -Wunreachable-code-loop-increment
+ if ((0)) {
+ continue;
+ }
+ DAWN_UNUSED(i);
+ FAIL();
+ }
+ for (auto i : Range(0, 0)) {
+ // Silence a -Wunreachable-code-loop-increment
+ if ((0)) {
+ continue;
+ }
+ DAWN_UNUSED(i);
+ FAIL();
+ }
+}
+
+// Test iterating with just an end.
+TEST(RangeTests, JustEnd) {
+ int count = 0;
+ for (auto i : Range(45)) {
+ ASSERT_EQ(count, i);
+ count++;
+ }
+ ASSERT_EQ(count, 45);
+}
+
+// Test iterating with a start and an end.
+TEST(RangeTests, StartAndEnd) {
+ int count = 18;
+ for (auto i : Range(18, 45)) {
+ ASSERT_EQ(count, i);
+ count++;
+ }
+ ASSERT_EQ(count, 45);
+}
+
+// Test iterating with a start and an end.
+TEST(RangeTests, StartAndEnd_ITyp) {
+ using Int = TypedInteger<struct IntT, int>;
+
+ Int count{18};
+ for (auto i : Range(Int{18}, Int{45})) {
+ ASSERT_EQ(count, i);
+ count++;
+ }
+ ASSERT_EQ(count, Int{45});
+}
+
+} // anonymous namespace
+} // namespace dawn