dingusppc/machines/machineproperties.h

194 lines
5.2 KiB
C
Raw Normal View History

2020-08-22 18:05:08 +00:00
#include "endianswap.h"
2021-09-15 22:46:38 +00:00
#include <loguru.hpp>
2021-02-14 15:41:48 +00:00
#include <algorithm>
2020-08-22 18:05:08 +00:00
#include <cinttypes>
2020-08-26 03:07:02 +00:00
#include <string>
2020-08-22 18:05:08 +00:00
#include <map>
#include <memory>
2021-09-15 22:46:38 +00:00
#include <limits>
#include <sstream>
2020-08-22 18:05:08 +00:00
#include <utility>
2020-10-09 13:58:47 +00:00
#include <vector>
2020-08-22 18:05:08 +00:00
2020-08-26 03:07:02 +00:00
#ifndef MACHINE_PROPERTIES_H
#define MACHINE_PROPERTIES_H
2020-08-22 18:05:08 +00:00
using namespace std;
2020-08-26 03:07:02 +00:00
#define ILLEGAL_DEVICE_VALUE 0x168A523B
/** Property types. */
enum PropType : int {
PROP_TYPE_UNKNOWN = 0,
PROP_TYPE_STRING = 1,
PROP_TYPE_INTEGER = 2,
};
2020-10-09 13:58:47 +00:00
/** Check types for property values. */
enum CheckType : int {
CHECK_TYPE_NONE = 0,
CHECK_TYPE_RANGE = 1,
CHECK_TYPE_LIST = 2,
2020-10-09 13:58:47 +00:00
};
/** Abstract base class for properties. */
class BasicProperty {
2020-08-22 18:05:08 +00:00
public:
BasicProperty(PropType type, string val) {
this->type = type;
set_string(val);
2020-08-22 18:05:08 +00:00
}
virtual ~BasicProperty() = default;
2020-10-09 13:58:47 +00:00
/* Clone method for copying derived property objects. */
virtual BasicProperty* clone() const = 0;
2020-09-20 21:25:29 +00:00
string get_string() {
return this->val;
2020-09-20 21:25:29 +00:00
}
void set_string(string str) {
this->val = str;
2020-08-22 18:05:08 +00:00
}
PropType get_type() {
return this->type;
}
protected:
PropType type;
string val;
};
2020-10-09 13:58:47 +00:00
/** 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); }
2020-09-20 21:25:29 +00:00
};
2020-10-09 13:58:47 +00:00
/** Property class that holds an integer value. */
class IntProperty : public BasicProperty {
2020-09-20 21:25:29 +00:00
public:
2020-10-09 13:58:47 +00:00
/* construct an integer property without value check. */
IntProperty(uint32_t val)
: BasicProperty(PROP_TYPE_INTEGER, to_string(val))
{
2020-10-09 13:58:47 +00:00
this->int_val = val;
this->min = std::numeric_limits<uint32_t>::min();
this->max = std::numeric_limits<uint32_t>::max();
this->check_type = CHECK_TYPE_NONE;
this->vec.clear();
2020-09-20 21:25:29 +00:00
}
2020-10-09 13:58:47 +00:00
/* 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))
{
2020-10-09 13:58:47 +00:00
this->int_val = val;
this->min = min;
this->max = max;
this->check_type = CHECK_TYPE_RANGE;
this->vec.clear();
}
2020-10-09 13:58:47 +00:00
/* construct an integer property with a list of valid values. */
IntProperty(uint32_t val, vector<uint32_t> vec)
: BasicProperty(PROP_TYPE_INTEGER, to_string(val))
{
this->int_val = val;
this->min = std::numeric_limits<uint32_t>::min();
this->max = std::numeric_limits<uint32_t>::max();
this->check_type = CHECK_TYPE_LIST;
2020-10-09 13:58:47 +00:00
this->vec = vec;
2020-09-20 21:25:29 +00:00
}
BasicProperty* clone() const { return new IntProperty(*this); }
2020-09-20 21:25:29 +00:00
uint32_t get_int() {
try {
uint32_t result = strtoul(this->get_string().c_str(), 0, 0);
2020-10-09 13:58:47 +00:00
/* perform value check */
if (!this->check_val(result)) {
LOG_F(ERROR, "Invalid property value %d!", result);
LOG_F(ERROR, "Valid values: %s!",
this->get_valid_values_as_str().c_str());
2020-10-09 14:33:17 +00:00
this->set_string(to_string(this->int_val));
} else {
this->int_val = result;
}
2020-09-20 21:25:29 +00:00
} catch (string bad_string) {
LOG_F(ERROR, "Could not convert string %s to an integer!",
bad_string.c_str());
}
return this->int_val;
2020-09-20 21:25:29 +00:00
}
string get_valid_values_as_str() {
stringstream ss;
switch (this->check_type) {
case CHECK_TYPE_RANGE:
ss << "[" << this->min << "..." << this->max << "]";
return ss.str();
case CHECK_TYPE_LIST: {
bool first = true;
for (auto it = begin(this->vec); it != end(this->vec); ++it) {
if (!first)
ss << ", ";
ss << *it;
first = false;
}
return ss.str();
}
default:
return string("None");
}
}
2020-10-09 13:58:47 +00:00
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_LIST:
2020-10-09 13:58:47 +00:00
if (find(this->vec.begin(), this->vec.end(), val) != this->vec.end())
return true;
else
return false;
default:
return true;
}
}
2020-09-20 21:25:29 +00:00
private:
2020-10-09 13:58:47 +00:00
uint32_t int_val;
CheckType check_type;
uint32_t min;
uint32_t max;
vector<uint32_t> vec;
2020-08-22 18:05:08 +00:00
};
2020-10-09 13:58:47 +00:00
/** Special map type for specifying machine presets. */
typedef map<string, BasicProperty*> PropMap;
2020-10-09 13:58:47 +00:00
/** Global map that holds settings for the running machine. */
extern map<string, unique_ptr<BasicProperty>> gMachineSettings;
2020-10-09 13:58:47 +00:00
/** Conveniency macros to hide complex casts. */
#define GET_STR_PROP(name) \
dynamic_cast<StrProperty*>(gMachineSettings.at(name).get())->get_string()
#define GET_INT_PROP(name) \
dynamic_cast<IntProperty*>(gMachineSettings.at(name).get())->get_int()
2020-09-20 21:25:29 +00:00
#endif /* MACHINE_PROPERTIES_H */