Add UncheckedRange

This commit is contained in:
Jean Pierre Cimalando 2021-03-19 21:05:01 +01:00
parent 09222d62bd
commit 9ebd02bf38
2 changed files with 48 additions and 9 deletions

View file

@ -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 <class Type>
template <class Type, bool Checked = true>
class Range {
// static_assert(std::is_arithmetic<Type>::value
// || (std::is_enum<Type>::value && std::is_same<typename std::underlying_type<Type>::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<Type>(0.0) };
Type _end { static_cast<Type>(0.0) };
};
template <class T> using UncheckedRange = Range<T, false>;
}
template <class Type>

View file

@ -62,6 +62,32 @@ TEST_CASE("[Range] Contains")
REQUIRE(floatRange.containsWithEnd(10.0));
}
TEST_CASE("[Range] Unchecked ranges")
{
sfz::UncheckedRange<int> 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<float> 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<int> { 1, 10 }.isValid());
REQUIRE(sfz::UncheckedRange<int> { 1, 1 }.isValid());
REQUIRE(sfz::UncheckedRange<float> { 1.0, 10.0 }.isValid());
REQUIRE(sfz::UncheckedRange<float> { 10.0, 10.0 }.isValid());
}
TEST_CASE("[Range] Clamp")
{
sfz::Range<int> intRange { 1, 10 };