From a3b17d46ce50589b13fc5d9cddb5aaa2d3f4cf04 Mon Sep 17 00:00:00 2001 From: Maxim Poliakovski Date: Fri, 9 Oct 2020 15:58:47 +0200 Subject: [PATCH] Attach value checks to properties. --- machines/machinefactory.cpp | 13 +++-- machines/machineproperties.h | 98 +++++++++++++++++++++++++----------- 2 files changed, 79 insertions(+), 32 deletions(-) diff --git a/machines/machinefactory.cpp b/machines/machinefactory.cpp index 7540dee..0a7596d 100644 --- a/machines/machinefactory.cpp +++ b/machines/machinefactory.cpp @@ -35,6 +35,7 @@ along with this program. If not, see . #include #include #include +#include #include using namespace std; @@ -65,10 +66,14 @@ static const map> rom_identity = { }; static const PropMap GossamerSettings = { - {"rambank1_size", new IntProperty("256")}, - {"rambank2_size", new IntProperty("0") }, - {"rambank3_size", new IntProperty("0") }, - {"gfxmem_size", new IntProperty("2") } + {"rambank1_size", + new IntProperty(256, vector({8, 16, 64, 128, 256}))}, + {"rambank2_size", + new IntProperty( 0, vector({0, 8, 16, 64, 128, 256}))}, + {"rambank3_size", + new IntProperty( 0, vector({0, 8, 16, 64, 128, 256}))}, + {"gfxmem_size", + new IntProperty( 2, vector({2, 4}))}, }; static const map>> machines = { diff --git a/machines/machineproperties.h b/machines/machineproperties.h index 026516f..95af22a 100644 --- a/machines/machineproperties.h +++ b/machines/machineproperties.h @@ -4,8 +4,8 @@ #include #include #include -#include #include +#include #ifndef MACHINE_PROPERTIES_H #define MACHINE_PROPERTIES_H @@ -21,6 +21,14 @@ enum PropType : int { PROP_TYPE_INTEGER = 2, }; +/** Check types for property values. */ +enum CheckType : int { + CHECK_TYPE_NONE = 0, + CHECK_TYPE_RANGE = 1, + CHECK_TYPE_CHOICE = 2, +}; + +/** Abstract base class for properties. */ class BasicProperty { public: BasicProperty(PropType type, string val) { @@ -30,6 +38,7 @@ public: virtual ~BasicProperty() = default; + /* Clone method for copying derived property objects. */ virtual BasicProperty* clone() const = 0; string get_string() { @@ -50,42 +59,49 @@ protected: }; +/** Property class that holds a string value. */ class StrProperty : public BasicProperty { public: StrProperty(string str) : BasicProperty(PROP_TYPE_STRING, str) {} BasicProperty* clone() const { return new StrProperty(*this); } - - uint32_t IntRep() { - try { - return strtoul(get_string().c_str(), 0, 0); - } catch (string bad_string) { - cerr << "Could not convert string " << bad_string << "to an ineteger!" << endl; - - return ILLEGAL_DEVICE_VALUE; - } - } }; +/** Property class that holds an integer value. */ class IntProperty : public BasicProperty { public: - IntProperty(string str) - : BasicProperty(PROP_TYPE_INTEGER, str) + /* construct an integer property without value check. */ + IntProperty(uint32_t val) + : BasicProperty(PROP_TYPE_INTEGER, to_string(val)) { - this->int_val = 0; - this->min = std::numeric_limits::min(); - this->max = std::numeric_limits::max(); + this->int_val = val; + this->min = std::numeric_limits::min(); + this->max = std::numeric_limits::max(); + this->check_type = CHECK_TYPE_NONE; + this->vec.clear(); } - IntProperty(string str, uint32_t min, uint32_t max) - : BasicProperty(PROP_TYPE_INTEGER, str) + /* construct an integer property with a predefined range. */ + IntProperty(uint32_t val, uint32_t min, uint32_t max) + : BasicProperty(PROP_TYPE_INTEGER, to_string(val)) { - this->int_val = 0; - this->min = min; - this->max = max; + this->int_val = val; + this->min = min; + this->max = max; + this->check_type = CHECK_TYPE_RANGE; + this->vec.clear(); + } - this->int_val = this->get_int(); + /* construct an integer property with a list of valid values. */ + IntProperty(uint32_t val, vector vec) + : BasicProperty(PROP_TYPE_INTEGER, to_string(val)) + { + this->int_val = val; + this->min = std::numeric_limits::min(); + this->max = std::numeric_limits::max(); + this->check_type = CHECK_TYPE_CHOICE; + this->vec = vec; } BasicProperty* clone() const { return new IntProperty(*this); } @@ -94,9 +110,9 @@ public: try { uint32_t result = strtoul(this->get_string().c_str(), 0, 0); - /* perform range check */ - if (result < this->min || result > this->max) { - LOG_F(ERROR, "Value %d out of range!", result); + /* perform value check */ + if (!this->check_val(result)) { + LOG_F(ERROR, "Invalid property value %d!", result); } else { this->int_val = result; } @@ -107,16 +123,42 @@ public: return this->int_val; } +protected: + bool check_val(uint32_t val) { + switch (this->check_type) { + case CHECK_TYPE_RANGE: + if (val < this->min || val > this->max) + return false; + else + return true; + case CHECK_TYPE_CHOICE: + if (find(this->vec.begin(), this->vec.end(), val) != this->vec.end()) + return true; + else + return false; + default: + return true; + } + } + private: - uint32_t int_val; - uint32_t min; - uint32_t max; + uint32_t int_val; + CheckType check_type; + uint32_t min; + uint32_t max; + vector vec; }; +/** Special map type for specifying machine presets. */ typedef map PropMap; +/** Global map that holds settings for the running machine. */ extern map> gMachineSettings; +/** Conveniency macros to hide complex casts. */ +#define GET_STR_PROP(name) \ + dynamic_cast(gMachineSettings.at(name).get())->get_string() + #define GET_INT_PROP(name) \ dynamic_cast(gMachineSettings.at(name).get())->get_int()