diff --git a/src/sfizz/Range.h b/src/sfizz/Range.h index 04240553..24785e9a 100644 --- a/src/sfizz/Range.h +++ b/src/sfizz/Range.h @@ -16,8 +16,9 @@ namespace sfz * @brief This class holds a range with functions to clamp and test if a value is in the range * * @tparam Type + * @tparam Checked whether this range adapts itself to guarantee (start<=end) */ -template +template class Range { // static_assert(std::is_arithmetic::value // || (std::is_enum::value && std::is_same::type, int>::value), @@ -27,7 +28,7 @@ public: constexpr Range() = default; constexpr Range(Type start, Type end) noexcept : _start(start) - , _end(max(start, end)) + , _end(Checked ? max(start, end) : end) { } @@ -43,16 +44,28 @@ public: void setStart(Type start) noexcept { _start = start; - if (start > _end) + if (Checked && start > _end) _end = start; } void setEnd(Type end) noexcept { _end = end; - if (end < _start) + if (Checked && end < _start) _start = end; } + + /** + * @brief Check whether the range verifies (start<=end) + */ + bool isValid() const noexcept + { + if (Checked) + return true; // always valid + else + return _start <= _end; + } + /** * @brief Clamp a value within the range including the endpoints * @@ -84,7 +97,7 @@ public: */ void shrinkIfSmaller(Type start, Type end) { - if (start > end) + if (Checked && start > end) std::swap(start, end); if (start > _start) @@ -96,12 +109,9 @@ public: void expandTo(Type value) { - if (containsWithEnd(value)) - return; - if (value > _end) _end = value; - else + else if (value < _start) _start = value; } @@ -134,6 +144,9 @@ private: Type _start { static_cast(0.0) }; Type _end { static_cast(0.0) }; }; + +template using UncheckedRange = Range; + } template diff --git a/tests/RangeT.cpp b/tests/RangeT.cpp index 5a6f95b5..67cc21ef 100644 --- a/tests/RangeT.cpp +++ b/tests/RangeT.cpp @@ -62,6 +62,32 @@ TEST_CASE("[Range] Contains") REQUIRE(floatRange.containsWithEnd(10.0)); } +TEST_CASE("[Range] Unchecked ranges") +{ + sfz::UncheckedRange intRange { 10, 1 }; + REQUIRE(intRange.getStart() == 10); + REQUIRE(intRange.getEnd() == 1); + REQUIRE(!intRange.isValid()); + for (int v : {0, 1, 5, 10}) { + REQUIRE(!intRange.contains(v)); + REQUIRE(!intRange.containsWithEnd(v)); + } + + sfz::UncheckedRange floatRange { 10.0, 1.0 }; + REQUIRE(floatRange.getStart() == 10.0f); + REQUIRE(floatRange.getEnd() == 1.0f); + REQUIRE(!floatRange.isValid()); + for (float v : {0.0f, 1.0f, 5.0f, 10.0f}) { + REQUIRE(!floatRange.contains(v)); + REQUIRE(!floatRange.containsWithEnd(v)); + } + + REQUIRE(sfz::UncheckedRange { 1, 10 }.isValid()); + REQUIRE(sfz::UncheckedRange { 1, 1 }.isValid()); + REQUIRE(sfz::UncheckedRange { 1.0, 10.0 }.isValid()); + REQUIRE(sfz::UncheckedRange { 10.0, 10.0 }.isValid()); +} + TEST_CASE("[Range] Clamp") { sfz::Range intRange { 1, 10 };