commit
d183c8c5a7
2 changed files with 48 additions and 9 deletions
|
|
@ -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
|
* @brief This class holds a range with functions to clamp and test if a value is in the range
|
||||||
*
|
*
|
||||||
* @tparam Type
|
* @tparam Type
|
||||||
|
* @tparam Checked whether this range adapts itself to guarantee (start<=end)
|
||||||
*/
|
*/
|
||||||
template <class Type>
|
template <class Type, bool Checked = true>
|
||||||
class Range {
|
class Range {
|
||||||
// static_assert(std::is_arithmetic<Type>::value
|
// static_assert(std::is_arithmetic<Type>::value
|
||||||
// || (std::is_enum<Type>::value && std::is_same<typename std::underlying_type<Type>::type, int>::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() = default;
|
||||||
constexpr Range(Type start, Type end) noexcept
|
constexpr Range(Type start, Type end) noexcept
|
||||||
: _start(start)
|
: _start(start)
|
||||||
, _end(max(start, end))
|
, _end(Checked ? max(start, end) : end)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -43,16 +44,28 @@ public:
|
||||||
void setStart(Type start) noexcept
|
void setStart(Type start) noexcept
|
||||||
{
|
{
|
||||||
_start = start;
|
_start = start;
|
||||||
if (start > _end)
|
if (Checked && start > _end)
|
||||||
_end = start;
|
_end = start;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setEnd(Type end) noexcept
|
void setEnd(Type end) noexcept
|
||||||
{
|
{
|
||||||
_end = end;
|
_end = end;
|
||||||
if (end < _start)
|
if (Checked && end < _start)
|
||||||
_start = end;
|
_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
|
* @brief Clamp a value within the range including the endpoints
|
||||||
*
|
*
|
||||||
|
|
@ -84,7 +97,7 @@ public:
|
||||||
*/
|
*/
|
||||||
void shrinkIfSmaller(Type start, Type end)
|
void shrinkIfSmaller(Type start, Type end)
|
||||||
{
|
{
|
||||||
if (start > end)
|
if (Checked && start > end)
|
||||||
std::swap(start, end);
|
std::swap(start, end);
|
||||||
|
|
||||||
if (start > _start)
|
if (start > _start)
|
||||||
|
|
@ -96,12 +109,9 @@ public:
|
||||||
|
|
||||||
void expandTo(Type value)
|
void expandTo(Type value)
|
||||||
{
|
{
|
||||||
if (containsWithEnd(value))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (value > _end)
|
if (value > _end)
|
||||||
_end = value;
|
_end = value;
|
||||||
else
|
else if (value < _start)
|
||||||
_start = value;
|
_start = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -134,6 +144,9 @@ private:
|
||||||
Type _start { static_cast<Type>(0.0) };
|
Type _start { static_cast<Type>(0.0) };
|
||||||
Type _end { static_cast<Type>(0.0) };
|
Type _end { static_cast<Type>(0.0) };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <class T> using UncheckedRange = Range<T, false>;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class Type>
|
template <class Type>
|
||||||
|
|
|
||||||
|
|
@ -62,6 +62,32 @@ TEST_CASE("[Range] Contains")
|
||||||
REQUIRE(floatRange.containsWithEnd(10.0));
|
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")
|
TEST_CASE("[Range] Clamp")
|
||||||
{
|
{
|
||||||
sfz::Range<int> intRange { 1, 10 };
|
sfz::Range<int> intRange { 1, 10 };
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue