refactor: remove constraint
- remove constraint because we no longer require them. constraints are put into seperate modules.
This commit is contained in:
@ -84,8 +84,6 @@ FILES
|
||||
yycc/windows/dialog.hpp
|
||||
yycc/windows/winfct.hpp
|
||||
yycc/windows/console.hpp
|
||||
yycc/constraint.hpp
|
||||
yycc/constraint/builder.hpp
|
||||
yycc/encoding/stl.hpp
|
||||
yycc/encoding/windows.hpp
|
||||
yycc/encoding/iconv.hpp
|
||||
|
||||
@ -1,78 +0,0 @@
|
||||
#pragma once
|
||||
#include "macro/class_copy_move.hpp"
|
||||
#include <functional>
|
||||
#include <stdexcept>
|
||||
#include <algorithm>
|
||||
|
||||
/// @brief The namespace containing generic constraint concept used varied in other modules.
|
||||
namespace yycc::constraint {
|
||||
|
||||
/// @brief Function prototype used in Constraint for checking whether given value is valid.
|
||||
/// @details Analyze given value, and return true if value is legal, otherwise false.
|
||||
template<typename T>
|
||||
using FnCheck = std::function<bool(const T&)>;
|
||||
/// @brief Function prototype used in Constraint for clamping given value into a valid value.
|
||||
/// @details Analyze given value, return clamped value.
|
||||
template<typename T>
|
||||
using FnClamp = std::function<T(const T&)>;
|
||||
|
||||
/**
|
||||
* @brief The constraint applied to settings to limit its stored value.
|
||||
* @tparam T The data type this constraint need to be processed with.
|
||||
* @details
|
||||
* Constraint class contains various features:
|
||||
* \li Check: Check whether given value is in range.
|
||||
* \li Clamp: Clamp given value into valid value.
|
||||
* Every instances of Constraint can have some, or none of these features.
|
||||
* So it is essential to check whether instance has corresponding features before using it.
|
||||
*/
|
||||
template<typename T>
|
||||
class Constraint {
|
||||
public:
|
||||
Constraint(FnCheck<T>&& fn_check, FnClamp<T>&& fn_clamp) :
|
||||
fn_check(std::move(fn_check)), fn_clamp(std::move(fn_clamp)) {}
|
||||
YYCC_DELETE_COPY(Constraint)
|
||||
YYCC_DEFAULT_MOVE(Constraint)
|
||||
|
||||
/**
|
||||
* @brief Perform Check feature.
|
||||
* @param[in] value The valid for checking.
|
||||
* @return True if valid is okey, otherwise false.
|
||||
* @exception std::logic_error Raised if this feature is not supported.
|
||||
*/
|
||||
bool check(const T& value) const {
|
||||
if (!support_check()) {
|
||||
throw std::logic_error("this Constraint do not support check operation");
|
||||
} else {
|
||||
return fn_check(value);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @brief Perform Clamp feature.
|
||||
* @param[in] value The valid for clamping.
|
||||
* @return The result after clamping.
|
||||
* @exception std::logic_error Raised if this feature is not supported.
|
||||
*/
|
||||
T clamp(const T& value) const {
|
||||
if (!support_clamp()) {
|
||||
throw std::logic_error("this Constraint do not support clamp operation");
|
||||
} else {
|
||||
return fn_clamp(value);
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief Check whether this Constraint support Check feature.
|
||||
/// @return True if it support, otherwise false.
|
||||
bool support_check() const noexcept { return this->fn_check != nullptr; }
|
||||
/// @brief Check whether this Constraint support Clamp feature.
|
||||
/// @return True if it support, otherwise false.
|
||||
bool support_clamp() const noexcept { return this->fn_clamp != nullptr; }
|
||||
|
||||
private:
|
||||
/// @brief Pointer to Check feature function.
|
||||
FnCheck<T> fn_check;
|
||||
/// @brief Pointer to Clamp feature function.
|
||||
FnClamp<T> fn_clamp;
|
||||
};
|
||||
|
||||
} // namespace yycc::core::constraint
|
||||
@ -1,71 +0,0 @@
|
||||
#pragma once
|
||||
#include "../constraint.hpp"
|
||||
#include <set>
|
||||
|
||||
/// @brief The namespace containing convenient function building common used Constraint instance.
|
||||
namespace yycc::constraint::builder {
|
||||
|
||||
/**
|
||||
* @brief Build Constraint for arithmetic values by minimum and maximum value range.
|
||||
* @tparam T An arithmetic or enum type (except bool) of underlying stored value.
|
||||
* @param[in] min_value The minimum value of range (inclusive).
|
||||
* @param[in] max_value The maximum value of range (inclusive).
|
||||
* @return The generated constraint instance which can be directly applied.
|
||||
*/
|
||||
template<typename T, std::enable_if_t<std::is_arithmetic_v<T> && !std::is_same_v<T, bool>, int> = 0>
|
||||
Constraint<T> min_max_constraint(T min_value, T max_value) {
|
||||
if (min_value > max_value) throw std::invalid_argument("the max value must be equal or greater than min value");
|
||||
|
||||
auto fn_check = [min_value, max_value](const T& val) -> bool { return (val <= max_value) && (val >= min_value); };
|
||||
auto fn_clamp = [min_value, max_value](const T& val) -> T { return std::clamp(val, min_value, max_value); };
|
||||
return Constraint<T>(std::move(fn_check), std::move(fn_clamp));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get constraint for enum values by enumerating all possible values.
|
||||
* @tparam T An enum type (except bool) of underlying stored value.
|
||||
* @param[in] il An initializer list storing all possible values.
|
||||
* @param[in] default_index The index of default value in given list.
|
||||
* @return The generated constraint instance which can be directly applied.
|
||||
*/
|
||||
template<typename T, std::enable_if_t<std::is_enum_v<T>, int> = 0>
|
||||
Constraint<T> enum_constraint(const std::initializer_list<T>& il, size_t default_index = 0u) {
|
||||
if (default_index >= il.size()) throw std::invalid_argument("the default index must be a valid index in given list");
|
||||
|
||||
T default_entry = il.begin()[default_index];
|
||||
std::set<T> entries(il);
|
||||
|
||||
auto fn_check = [entries](const T& val) -> bool { return entries.contains(val); };
|
||||
auto fn_clamp = [entries, default_entry](const T& val) -> T {
|
||||
if (entries.contains(val)) return val;
|
||||
else return default_entry;
|
||||
};
|
||||
return Constraint<T>(std::move(fn_check), fn_clamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get constraint for string values by enumerating all possible values.
|
||||
* @param[in] il An initializer list storing all possible values.
|
||||
* @param[in] default_index The index of default value in given list.
|
||||
* @return The generated constraint instance which can be directly applied.
|
||||
*/
|
||||
inline Constraint<std::u8string> strenum_constraint(const std::initializer_list<std::u8string_view>& il, size_t default_index = 0u) {
|
||||
if (default_index >= il.size()) throw std::invalid_argument("the default index must be a valid index in given list");
|
||||
|
||||
std::u8string default_entry = std::u8string(il.begin()[default_index]);
|
||||
std::set<std::u8string> entries;
|
||||
for (const auto& i : il) {
|
||||
entries.emplace(i);
|
||||
}
|
||||
|
||||
auto fn_check = [entries](const std::u8string& val) -> bool { return entries.contains(val); };
|
||||
auto fn_clamp = [entries, default_entry](const std::u8string& val) -> std::u8string {
|
||||
if (entries.contains(val)) return val;
|
||||
else return default_entry;
|
||||
};
|
||||
return Constraint<std::u8string>(std::move(fn_check), fn_clamp);
|
||||
}
|
||||
|
||||
} // namespace yycc::constraint::builder
|
||||
|
||||
#undef NS_YYCC_STRING
|
||||
@ -14,8 +14,6 @@ PRIVATE
|
||||
yycc/macro/ptr_size_detector.cpp
|
||||
yycc/macro/stl_detector.cpp
|
||||
yycc/flag_enum.cpp
|
||||
yycc/constraint.cpp
|
||||
yycc/constraint/builder.cpp
|
||||
yycc/patch/ptr_pad.cpp
|
||||
yycc/patch/fopen.cpp
|
||||
yycc/patch/stream.cpp
|
||||
|
||||
@ -1,50 +0,0 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <yycc.hpp>
|
||||
#include <yycc/constraint.hpp>
|
||||
|
||||
#include <yycc/prelude.hpp>
|
||||
|
||||
#define CONSTRAINT ::yycc::constraint::Constraint
|
||||
|
||||
namespace yycctest::constraint {
|
||||
|
||||
template<typename T>
|
||||
bool check(const T& value) {
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T clamp(const T& value) {
|
||||
return value;
|
||||
}
|
||||
|
||||
TEST(Constraint, Normal) {
|
||||
CONSTRAINT<u32> instance(check<u32>, clamp<u32>);
|
||||
EXPECT_TRUE(instance.support_check());
|
||||
EXPECT_TRUE(instance.support_clamp());
|
||||
EXPECT_FALSE(instance.check(0));
|
||||
EXPECT_EQ(instance.clamp(0), 0);
|
||||
}
|
||||
|
||||
TEST(Constraint, SomeNone) {
|
||||
{
|
||||
CONSTRAINT<u32> instance(check<u32>, nullptr);
|
||||
EXPECT_TRUE(instance.support_check());
|
||||
EXPECT_FALSE(instance.support_clamp());
|
||||
EXPECT_FALSE(instance.check(0));
|
||||
}
|
||||
{
|
||||
CONSTRAINT<u32> instance(nullptr, clamp<u32>);
|
||||
EXPECT_FALSE(instance.support_check());
|
||||
EXPECT_TRUE(instance.support_clamp());
|
||||
EXPECT_EQ(instance.clamp(0), 0);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Constraint, AllNone) {
|
||||
CONSTRAINT<u32> instance(nullptr, nullptr);
|
||||
EXPECT_FALSE(instance.support_check());
|
||||
EXPECT_FALSE(instance.support_clamp());
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,79 +0,0 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <yycc.hpp>
|
||||
#include <yycc/constraint/builder.hpp>
|
||||
|
||||
#include <yycc/prelude.hpp>
|
||||
|
||||
#define BUILDER ::yycc::constraint::builder
|
||||
using namespace std::literals::string_view_literals;
|
||||
|
||||
namespace yycctest::constraint::builder {
|
||||
|
||||
#define TEST_SUCCESS(constraint, value) \
|
||||
EXPECT_TRUE(constraint.check(value)); \
|
||||
EXPECT_EQ(constraint.clamp(value), value);
|
||||
|
||||
#define TEST_FAIL(constraint, value, clamped_value) \
|
||||
EXPECT_FALSE(constraint.check(value)); \
|
||||
EXPECT_EQ(constraint.clamp(value), clamped_value);
|
||||
|
||||
TEST(ConstraintBuilder, MinMaxConstraint) {
|
||||
// Integral type
|
||||
{
|
||||
auto c = BUILDER::min_max_constraint<i32>(5, 61);
|
||||
ASSERT_TRUE(c.support_check());
|
||||
ASSERT_TRUE(c.support_clamp());
|
||||
TEST_SUCCESS(c, 5);
|
||||
TEST_SUCCESS(c, 6);
|
||||
TEST_SUCCESS(c, 61);
|
||||
TEST_FAIL(c, -2, 5);
|
||||
TEST_FAIL(c, 0, 5);
|
||||
TEST_FAIL(c, 66, 61);
|
||||
}
|
||||
// Unisgned integral type
|
||||
{
|
||||
auto c = BUILDER::min_max_constraint<u32>(5, 61);
|
||||
ASSERT_TRUE(c.support_check());
|
||||
ASSERT_TRUE(c.support_clamp());
|
||||
TEST_SUCCESS(c, 5);
|
||||
TEST_SUCCESS(c, 6);
|
||||
TEST_SUCCESS(c, 61);
|
||||
TEST_FAIL(c, 0, 5);
|
||||
TEST_FAIL(c, 66, 61);
|
||||
}
|
||||
// Float point type
|
||||
{
|
||||
auto c = BUILDER::min_max_constraint<f32>(5.0f, 61.0f);
|
||||
ASSERT_TRUE(c.support_check());
|
||||
ASSERT_TRUE(c.support_clamp());
|
||||
TEST_SUCCESS(c, 5.0f);
|
||||
TEST_SUCCESS(c, 6.0f);
|
||||
TEST_SUCCESS(c, 61.0f);
|
||||
TEST_FAIL(c, 0.0f, 5.0f);
|
||||
TEST_FAIL(c, 66.0f, 61.0f);
|
||||
}
|
||||
}
|
||||
|
||||
enum class TestEnum : u8 { Entry1 = 0, Entry2 = 1, Entry3 = 2 };
|
||||
|
||||
TEST(ConstraintBuilder, EnumConstraint) {
|
||||
auto c = BUILDER::enum_constraint({TestEnum::Entry1, TestEnum::Entry2, TestEnum::Entry3}, 1u);
|
||||
ASSERT_TRUE(c.support_check());
|
||||
ASSERT_TRUE(c.support_clamp());
|
||||
TEST_SUCCESS(c, TestEnum::Entry1);
|
||||
TEST_SUCCESS(c, TestEnum::Entry2);
|
||||
TEST_SUCCESS(c, TestEnum::Entry3);
|
||||
TEST_FAIL(c, static_cast<TestEnum>(UINT8_C(61)), TestEnum::Entry2);
|
||||
}
|
||||
|
||||
TEST(ConstraintBuilder, StrEnumConstraint) {
|
||||
auto c = BUILDER::strenum_constraint({u8"first-entry"sv, u8"second-entry"sv, u8"third-entry"sv}, 1u);
|
||||
ASSERT_TRUE(c.support_check());
|
||||
ASSERT_TRUE(c.support_clamp());
|
||||
TEST_SUCCESS(c, u8"first-entry");
|
||||
TEST_SUCCESS(c, u8"second-entry");
|
||||
TEST_SUCCESS(c, u8"third-entry");
|
||||
TEST_FAIL(c, u8"wtf?", u8"second-entry");
|
||||
}
|
||||
|
||||
} // namespace yycctest::constraint::builder
|
||||
Reference in New Issue
Block a user