一、用户预设内容
1、打印机预设
%appdata%\OrcaSlicer\user\default\machine
2、耗材预设
%appdata%\OrcaSlicer\user\default\filament
3、工艺预设
%appdata%\OrcaSlicer\user\default\process
二、预设数据类型
2.1 ConfigOptionType
在OrcaSlicer\src\libslic3r\Config.hpp文件中定义
enum ConfigOptionType {
coVectorType = 0x4000,
coNone = 0,
// single float
coFloat = 1,
// vector of floats
coFloats = coFloat + coVectorType,
// single int
coInt = 2,
// vector of ints
coInts = coInt + coVectorType,
// single string
coString = 3,
// vector of strings
coStrings = coString + coVectorType,
// percent value. Currently only used for infill.
coPercent = 4,
// percents value. Currently used for retract before wipe only.
coPercents = coPercent + coVectorType,
// a fraction or an absolute value
coFloatOrPercent = 5,
// vector of the above
coFloatsOrPercents = coFloatOrPercent + coVectorType,
// single 2d point (Point2f). Currently not used.
coPoint = 6,
// vector of 2d points (Point2f). Currently used for the definition of the print bed and for the extruder offsets.
coPoints = coPoint + coVectorType,
coPoint3 = 7,
// coPoint3s = coPoint3 + coVectorType,
// single boolean value
coBool = 8,
// vector of boolean values
coBools = coBool + coVectorType,
// a generic enum
coEnum = 9,
// BBS: vector of enums
coEnums = coEnum + coVectorType,
};
包含17种数据类型,分别为:
浮点型-coFloat 浮点型数组-coFloats
整型-coInt 整形数组-coInts
字符串型-coString 字符串数组-coStrings
百分比型-coPercent 百分比数组-coPercents
浮点或百分比-coFloatOrPercent 浮点或百分比数组-coFloatPercents
2维点-coPoint 2维点数组-coPoints
3维点-coPoint3
布尔型-coBool 布尔数组-coBools
枚举型-coEnum 枚举数组-coEnum
三、预设数据类型类
3.1 ConfigOption配置选项 纯虚类
此类在OrcaSlicer\src\libslic3r\Config.hpp文件中定义
此类是一个纯虚类,是所有数据类型类的基类,是一个接口类。
class ConfigOption {
public:
virtual ~ConfigOption() {}
virtual ConfigOptionType type() const = 0;
virtual std::string serialize() const = 0;
virtual bool deserialize(const std::string &str, bool append = false) = 0;
virtual ConfigOption* clone() const = 0;
// Set a value from a ConfigOption. The two options should be compatible.
virtual void set(const ConfigOption *option) = 0;
virtual int getInt() const { throw BadOptionTypeException("Calling ConfigOption::getInt on a non-int ConfigOption"); }
virtual double getFloat() const { throw BadOptionTypeException("Calling ConfigOption::getFloat on a non-float ConfigOption"); }
virtual bool getBool() const { throw BadOptionTypeException("Calling ConfigOption::getBool on a non-boolean ConfigOption"); }
virtual void setInt(int /* val */) { throw BadOptionTypeException("Calling ConfigOption::setInt on a non-int ConfigOption"); }
virtual bool operator==(const ConfigOption &rhs) const = 0;
bool operator!=(const ConfigOption &rhs) const { return ! (*this == rhs); }
virtual size_t hash() const throw() = 0;
bool is_scalar() const { return (int(this->type()) & int(coVectorType)) == 0; }
bool is_vector() const { return ! this->is_scalar(); }
// If this option is nullable, then it may have its value or values set to nil.
virtual bool nullable() const { return false; }
// A scalar is nil, or all values of a vector are nil.
virtual bool is_nil() const { return false; }
// Is this option overridden by another option?
// An option overrides another option if it is not nil and not equal.
virtual bool overriden_by(const ConfigOption *rhs) const {
assert(! this->nullable() && ! rhs->nullable());
return *this != *rhs;
}
// Apply an override option, possibly a nullable one.
virtual bool apply_override(const ConfigOption *rhs) {
if (*this == *rhs)
return false;
*this = *rhs;
return true;
}
};
3.1.1 纯虚函数
virtual ConfigOptionType type() const = 0;
获取类对应的数据类型
virtual std::string serialize() const = 0;
将数据字段值,序列化为字符串
virtual bool deserialize(const std::string &str, bool append = false) = 0;
将字符串反序列化,为数据字段值
virtual ConfigOption* clone() const = 0;
克隆类对象
virtual void set(const ConfigOption *option) = 0;
使用对象指针对数据进行设置
virtual bool operator==(const ConfigOption &rhs) const = 0;
==操作符重载
virtual size_t hash() const throw() = 0;
获取哈希值
3.1.2 虚函数
virtual int getInt() const
获取整形值
virtual double getFloat() const
获取浮点类型值
virtual bool getBool()
获取布尔值
virtual void setInt(int /* val */)
使用整形进行赋值
virtual bool nullable() const
是否为空值
virtual bool is_nil() const
是否为nil
virtual bool overriden_by(const ConfigOption *rhs) const
virtual bool apply_override(const ConfigOption *rhs)
3.1.3 普通函数
bool operator!=(const ConfigOption &rhs) const
bool is_scalar() const
是否为单个数据
bool is_vector() const
是否为数组数据
3.2 ConfigOptionSingle 配置选项单数据 模板基类
此类与之后的ConfigOptionVector相对应
此类在OrcaSlicer\src\libslic3r\Config.hpp文件中定义,是从ConfigOption派生而来
此类是一个模板类,是bool,int,float,string,point,enum类型类的基类
template <class T>
class ConfigOptionSingle : public ConfigOption {
public:
T value;
explicit ConfigOptionSingle(T value) : value(std::move(value)) {}
operator T() const { return this->value; }
void set(const ConfigOption *rhs) override
{
if (rhs->type() != this->type())
throw ConfigurationError("ConfigOptionSingle: Assigning an incompatible type");
assert(dynamic_cast<const ConfigOptionSingle<T>*>(rhs));
this->value = static_cast<const ConfigOptionSingle<T>*>(rhs)->value;
}
bool operator==(const ConfigOption &rhs) const override
{
if (rhs.type() != this->type())
throw ConfigurationError("ConfigOptionSingle: Comparing incompatible types");
assert(dynamic_cast<const ConfigOptionSingle<T>*>(&rhs));
return this->value == static_cast<const ConfigOptionSingle<T>*>(&rhs)->value;
}
bool operator==(const T &rhs) const throw() { return this->value == rhs; }
bool operator!=(const T &rhs) const throw() { return this->value != rhs; }
bool operator< (const T &rhs) const throw() { return this->value < rhs; }
size_t hash() const throw() override { return std::hash<T>{}(this->value); }
private:
friend class cereal::access;
template<class Archive> void serialize(Archive & ar) { ar(this->value); }
};
3.2.1 成员变量
T value 用来保存数据类型的值
3.2.2 成员函数
explicit ConfigOptionSingle(T value)
使用explicit进行修饰,防止隐式转换。
operator T() const
括号操作符重载,可以直接通过小括号直接获取到数据。
void set(const ConfigOption *rhs) override
如果类型不同,会抛异常。如果不能动态转换成ConfigOptionSingle类指针,会触发assert。
通过静态类型转换,来获取到参数对象value的值,进行赋值。
size_t hash() const
使用std::hash来获取哈希值
3.3 ConfigOptionVectorBase 配置选项数组数据 纯虚类
此类在OrcaSlicer\src\libslic3r\Config.hpp文件中定义
此类是一个纯虚类,是所有数组数据类的基类,是一个接口类,是从ConfigOption类派生而来。
数组数据类型包括:bools, ints, floats, strings, points
class ConfigOptionVectorBase : public ConfigOption {
public:
// Currently used only to initialize the PlaceholderParser.
virtual std::vector<std::string> vserialize() const = 0;
// Set from a vector of ConfigOptions.
// If the rhs ConfigOption is scalar, then its value is used,
// otherwise for each of rhs, the first value of a vector is used.
// This function is useful to collect values for multiple extrder / filament settings.
virtual void set(const std::vector<const ConfigOption*> &rhs) = 0;
// Set a single vector item from either a scalar option or the first value of a vector option.vector of ConfigOptions.
// This function is useful to split values from multiple extrder / filament settings into separate configurations.
virtual void set_at(const ConfigOption *rhs, size_t i, size_t j) = 0;
// Resize the vector of values, copy the newly added values from opt_default if provided.
virtual void resize(size_t n, const ConfigOption *opt_default = nullptr) = 0;
// Clear the values vector.
virtual void clear() = 0;
// Get size of this vector.
virtual size_t size() const = 0;
// Is this vector empty?
virtual bool empty() const = 0;
// Is the value nil? That should only be possible if this->nullable().
virtual bool is_nil(size_t idx) const = 0;
// We just overloaded and hid two base class virtual methods.
// Let's show it was intentional (warnings).
using ConfigOption::set;
using ConfigOption::is_nil;
protected:
// Used to verify type compatibility when assigning to / from a scalar ConfigOption.
ConfigOptionType scalar_type() const { return static_cast<ConfigOptionType>(this->type() - coVectorType); }
};
3.3.1 纯虚函数
virtual std::vector<std::string> vserialize() const = 0;
将数组数据序列化成字符串类型的vector
virtual void set(const std::vector<const ConfigOption*> &rhs) = 0;
通过vector进行赋值
virtual void resize(size_t n, const ConfigOption *opt_default = nullptr) = 0;
使用默认值进行填充
virtual void clear() = 0;
清空数据
virtual size_t size() const = 0;
获取数据内容数量
virtual bool empty() const = 0;
是否为空
virtual bool is_nil(size_t idx) const = 0;
某个数据是否为空
3.4 ConfigOptionVector 配置选项数组数据 模板基类
此类在OrcaSlicer\src\libslic3r\Config.hpp文件中定义,是从ConfigOptionVectorBase派生而来。
此类是与前面的ConfigOptionSingle对应
此类是一个模板类,是bools, ints, floats, strings, points类型类的基类
template <class T>
class ConfigOptionVector : public ConfigOptionVectorBase
{
public:
ConfigOptionVector() {}
explicit ConfigOptionVector(size_t n, const T &value) : values(n, value) {}
explicit ConfigOptionVector(std::initializer_list<T> il) : values(std::move(il)) {}
explicit ConfigOptionVector(const std::vector<T> &values) : values(values) {}
explicit ConfigOptionVector(std::vector<T> &&values) : values(std::move(values)) {}
std::vector<T> values;
void set(const ConfigOption *rhs) override
{
if (rhs->type() != this->type())
throw ConfigurationError("ConfigOptionVector: Assigning an incompatible type");
assert(dynamic_cast<const ConfigOptionVector<T>*>(rhs));
this->values = static_cast<const ConfigOptionVector<T>*>(rhs)->values;
}
// Set from a vector of ConfigOptions.
// If the rhs ConfigOption is scalar, then its value is used,
// otherwise for each of rhs, the first value of a vector is used.
// This function is useful to collect values for multiple extrder / filament settings.
void set(const std::vector<const ConfigOption*> &rhs) override
{
this->values.clear();
this->values.reserve(rhs.size());
for (const ConfigOption *opt : rhs) {
if (opt->type() == this->type()) {
auto other = static_cast<const ConfigOptionVector<T>*>(opt);
if (other->values.empty())
throw ConfigurationError("ConfigOptionVector::set(): Assigning from an empty vector");
this->values.emplace_back(other->values.front());
} else if (opt->type() == this->scalar_type())
this->values.emplace_back(static_cast<const ConfigOptionSingle<T>*>(opt)->value);
else
throw ConfigurationError("ConfigOptionVector::set():: Assigning an incompatible type");
}
}
// Set a single vector item from either a scalar option or the first value of a vector option.vector of ConfigOptions.
// This function is useful to split values from multiple extrder / filament settings into separate configurations.
void set_at(const ConfigOption *rhs, size_t i, size_t j) override
{
// It is expected that the vector value has at least one value, which is the default, if not overwritten.
assert(! this->values.empty());
if (this->values.size() <= i) {
// Resize this vector, fill in the new vector fields with the copy of the first field.
T v = this->values.front();
this->values.resize(i + 1, v);
}
if (rhs->type() == this->type()) {
// Assign the first value of the rhs vector.
auto other = static_cast<const ConfigOptionVector<T>*>(rhs);
if (other->values.empty())
throw ConfigurationError("ConfigOptionVector::set_at(): Assigning from an empty vector");
this->values[i] = other->get_at(j);
} else if (rhs->type() == this->scalar_type())
this->values[i] = static_cast<const ConfigOptionSingle<T>*>(rhs)->value;
else
throw ConfigurationError("ConfigOptionVector::set_at(): Assigning an incompatible type");
}
const T& get_at(size_t i) const
{
assert(! this->values.empty());
return (i < this->values.size()) ? this->values[i] : this->values.front();
}
T& get_at(size_t i) { return const_cast<T&>(std::as_const(*this).get_at(i)); }
// Resize this vector by duplicating the /*last*/first value.
// If the current vector is empty, the default value is used instead.
// BBS: support scaler opt_default
void resize(size_t n, const ConfigOption *opt_default = nullptr) override
{
//assert(opt_default == nullptr || opt_default->is_vector());
// assert(opt_default == nullptr || dynamic_cast<ConfigOptionVector<T>>(opt_default));
assert(! this->values.empty() || opt_default != nullptr);
if (n == 0)
this->values.clear();
else if (n < this->values.size())
this->values.erase(this->values.begin() + n, this->values.end());
else if (n > this->values.size()) {
if (this->values.empty()) {
if (opt_default == nullptr) {
throw ConfigurationError("ConfigOptionVector::resize(): No default value provided.");
}
else if (opt_default->is_vector()) {
if (opt_default->type() != this->type())
throw ConfigurationError("ConfigOptionVector::resize(): Extending with an incompatible type.");
this->values.resize(n, static_cast<const ConfigOptionVector<T>*>(opt_default)->values.front());
}
else {
if (opt_default->type() != this->scalar_type())
throw ConfigurationError("ConfigOptionVector::resize(): Extending with an incompatible type.");
this->values.resize(n, static_cast<const ConfigOptionSingle<T>*>(opt_default)->value);
}
} else {
// Resize by duplicating the last value.
this->values.resize(n, this->values./*back*/front());
}
}
}
// Clear the values vector.
void clear() override { this->values.clear(); }
size_t size() const override { return this->values.size(); }
bool empty() const override { return this->values.empty(); }
bool operator==(const ConfigOption &rhs) const override
{
if (rhs.type() != this->type())
throw ConfigurationError("ConfigOptionVector: Comparing incompatible types");
assert(dynamic_cast<const ConfigOptionVector<T>*>(&rhs));
return this->values == static_cast<const ConfigOptionVector<T>*>(&rhs)->values;
}
bool operator==(const std::vector<T> &rhs) const throw() { return this->values == rhs; }
bool operator!=(const std::vector<T> &rhs) const throw() { return this->values != rhs; }
size_t hash() const throw() override {
std::hash<T> hasher;
size_t seed = 0;
for (const auto &v : this->values)
boost::hash_combine(seed, hasher(v));
return seed;
}
// Is this option overridden by another option?
// An option overrides another option if it is not nil and not equal.
bool overriden_by(const ConfigOption *rhs) const override {
if (this->nullable())
throw ConfigurationError("Cannot override a nullable ConfigOption.");
if (rhs->type() != this->type())
throw ConfigurationError("ConfigOptionVector.overriden_by() applied to different types.");
auto rhs_vec = static_cast<const ConfigOptionVector<T>*>(rhs);
if (! rhs->nullable())
// Overridding a non-nullable object with another non-nullable object.
return this->values != rhs_vec->values;
size_t i = 0;
size_t cnt = std::min(this->size(), rhs_vec->size());
for (; i < cnt; ++ i)
if (! rhs_vec->is_nil(i) && this->values[i] != rhs_vec->values[i])
return true;
for (; i < rhs_vec->size(); ++ i)
if (! rhs_vec->is_nil(i))
return true;
return false;
}
// Apply an override option, possibly a nullable one.
bool apply_override(const ConfigOption *rhs) override {
if (this->nullable())
throw ConfigurationError("Cannot override a nullable ConfigOption.");
if (rhs->type() != this->type())
throw ConfigurationError("ConfigOptionVector.apply_override() applied to different types.");
auto rhs_vec = static_cast<const ConfigOptionVector<T>*>(rhs);
if (! rhs->nullable()) {
// Overridding a non-nullable object with another non-nullable object.
if (this->values != rhs_vec->values) {
this->values = rhs_vec->values;
return true;
}
return false;
}
size_t cnt = std::min(this->size(), rhs_vec->size());
if (cnt < 1)
return false;
if (this->values.empty())
this->values.resize(rhs_vec->size());
else
this->values.resize(rhs_vec->size(), this->values.front());
bool modified = false;
auto default_value = this->values[0];
for (size_t i = 0; i < rhs_vec->size(); ++i) {
if (!rhs_vec->is_nil(i)) {
this->values[i] = rhs_vec->values[i];
modified = true;
} else {
this->values[i] = default_value;
}
}
return modified;
}
private:
friend class cereal::access;
template<class Archive> void serialize(Archive & ar) { ar(this->values); }
};
3.4.1 成员变量
std::vector<T> values;
3.4.2 成员函数
ConfigOptionVector()
explicit ConfigOptionVector(size_t n, const T &value)
explicit ConfigOptionVector(std::initializer_list<T> il)
explicit ConfigOptionVector(const std::vector<T> &values)
explicit ConfigOptionVector(std::vector<T> &&values)
5种构造函数
3.5 由ConfigOptionSingle派生的类
3.5.1 ConfigOptionFloat
class ConfigOptionFloat : public ConfigOptionSingle<double>
{
public:
ConfigOptionFloat() : ConfigOptionSingle<double>(0) {}
explicit ConfigOptionFloat(double _value) : ConfigOptionSingle<double>(_value) {}
static ConfigOptionType static_type() { return coFloat; }
ConfigOptionType type() const override { return static_type(); }
double getFloat() const override { return this->value; }
ConfigOption* clone() const override { return new ConfigOptionFloat(*this); }
bool operator==(const ConfigOptionFloat &rhs) const throw() { return this->value == rhs.value; }
bool operator< (const ConfigOptionFloat &rhs) const throw() { return this->value < rhs.value; }
std::string serialize() const override
{
std::ostringstream ss;
ss << this->value;
return ss.str();
}
bool deserialize(const std::string &str, bool append = false) override
{
UNUSED(append);
std::istringstream iss(str);
iss >> this->value;
return !iss.fail();
}
ConfigOptionFloat& operator=(const ConfigOption *opt)
{
this->set(opt);
return *this;
}
private:
friend class cereal::access;
template<class Archive> void serialize(Archive &ar) { ar(cereal::base_class<ConfigOptionSingle<double>>(this)); }
};
3.5.2 ConfigOptionInt
class ConfigOptionInt : public ConfigOptionSingle<int>
{
public:
ConfigOptionInt() : ConfigOptionSingle<int>(0) {}
explicit ConfigOptionInt(int value) : ConfigOptionSingle<int>(value) {}
explicit ConfigOptionInt(double _value) : ConfigOptionSingle<int>(int(floor(_value + 0.5))) {}
static ConfigOptionType static_type() { return coInt; }
ConfigOptionType type() const override { return static_type(); }
int getInt() const override { return this->value; }
void setInt(int val) override { this->value = val; }
ConfigOption* clone() const override { return new ConfigOptionInt(*this); }
bool operator==(const ConfigOptionInt &rhs) const throw() { return this->value == rhs.value; }
std::string serialize() const override
{
std::ostringstream ss;
ss << this->value;
return ss.str();
}
bool deserialize(const std::string &str, bool append = false) override
{
UNUSED(append);
std::istringstream iss(str);
iss >> this->value;
return !iss.fail();
}
ConfigOptionInt& operator=(const ConfigOption *opt)
{
this->set(opt);
return *this;
}
private:
friend class cereal::access;
template<class Archive> void serialize(Archive &ar) { ar(cereal::base_class<ConfigOptionSingle<int>>(this)); }
};
3.5.3 ConfigOptionString
class ConfigOptionString : public ConfigOptionSingle<std::string>
{
public:
ConfigOptionString() : ConfigOptionSingle<std::string>(std::string{}) {}
explicit ConfigOptionString(std::string value) : ConfigOptionSingle<std::string>(std::move(value)) {}
static ConfigOptionType static_type() { return coString; }
ConfigOptionType type() const override { return static_type(); }
ConfigOption* clone() const override { return new ConfigOptionString(*this); }
ConfigOptionString& operator=(const ConfigOption *opt) { this->set(opt); return *this; }
bool operator==(const ConfigOptionString &rhs) const throw() { return this->value == rhs.value; }
bool operator< (const ConfigOptionString &rhs) const throw() { return this->value < rhs.value; }
bool empty() const { return this->value.empty(); }
std::string serialize() const override
{
return escape_string_cstyle(this->value);
}
bool deserialize(const std::string &str, bool append = false) override
{
UNUSED(append);
return unescape_string_cstyle(str, this->value);
}
private:
friend class cereal::access;
template<class Archive> void serialize(Archive &ar) { ar(cereal::base_class<ConfigOptionSingle<std::string>>(this)); }
};
3.5.4 ConfigOptionPoint
using Vec2d = Eigen::Matrix<double, 2, 1, Eigen::DontAlign>;
class ConfigOptionPoint : public ConfigOptionSingle<Vec2d>
{
public:
ConfigOptionPoint() : ConfigOptionSingle<Vec2d>(Vec2d(0,0)) {}
explicit ConfigOptionPoint(const Vec2d &value) : ConfigOptionSingle<Vec2d>(value) {}
static ConfigOptionType static_type() { return coPoint; }
ConfigOptionType type() const override { return static_type(); }
ConfigOption* clone() const override { return new ConfigOptionPoint(*this); }
ConfigOptionPoint& operator=(const ConfigOption *opt) { this->set(opt); return *this; }
bool operator==(const ConfigOptionPoint &rhs) const throw() { return this->value == rhs.value; }
bool operator< (const ConfigOptionPoint &rhs) const throw() { return this->value < rhs.value; }
std::string serialize() const override
{
std::ostringstream ss;
ss << this->value(0);
ss << ",";
ss << this->value(1);
return ss.str();
}
bool deserialize(const std::string &str, bool append = false) override
{
UNUSED(append);
char dummy;
return sscanf(str.data(), " %lf , %lf %c", &this->value(0), &this->value(1), &dummy) == 2 ||
sscanf(str.data(), " %lf x %lf %c", &this->value(0), &this->value(1), &dummy) == 2;
}
private:
friend class cereal::access;
template<class Archive> void serialize(Archive &ar) { ar(cereal::base_class<ConfigOptionSingle<Vec2d>>(this)); }
};
3.5.5 ConfigOptionPoint3
using Vec3d = Eigen::Matrix<double, 3, 1, Eigen::DontAlign>;
class ConfigOptionPoint3 : public ConfigOptionSingle<Vec3d>
{
public:
ConfigOptionPoint3() : ConfigOptionSingle<Vec3d>(Vec3d(0,0,0)) {}
explicit ConfigOptionPoint3(const Vec3d &value) : ConfigOptionSingle<Vec3d>(value) {}
static ConfigOptionType static_type() { return coPoint3; }
ConfigOptionType type() const override { return static_type(); }
ConfigOption* clone() const override { return new ConfigOptionPoint3(*this); }
ConfigOptionPoint3& operator=(const ConfigOption *opt) { this->set(opt); return *this; }
bool operator==(const ConfigOptionPoint3 &rhs) const throw() { return this->value == rhs.value; }
bool operator< (const ConfigOptionPoint3 &rhs) const throw()
{ return this->value.x() < rhs.value.x() || (this->value.x() == rhs.value.x() && (this->value.y() < rhs.value.y() || (this->value.y() == rhs.value.y() && this->value.z() < rhs.value.z()))); }
std::string serialize() const override
{
std::ostringstream ss;
ss << this->value(0);
ss << ",";
ss << this->value(1);
ss << ",";
ss << this->value(2);
return ss.str();
}
bool deserialize(const std::string &str, bool append = false) override
{
UNUSED(append);
char dummy;
return sscanf(str.data(), " %lf , %lf , %lf %c", &this->value(0), &this->value(1), &this->value(2), &dummy) == 3 ||
sscanf(str.data(), " %lf x %lf x %lf %c", &this->value(0), &this->value(1), &this->value(2), &dummy) == 3;
}
private:
friend class cereal::access;
template<class Archive> void serialize(Archive &ar) { ar(cereal::base_class<ConfigOptionSingle<Vec3d>>(this)); }
};
3.5.6 ConfigOptionBool
class ConfigOptionBool : public ConfigOptionSingle<bool>
{
public:
ConfigOptionBool() : ConfigOptionSingle<bool>(false) {}
explicit ConfigOptionBool(bool _value) : ConfigOptionSingle<bool>(_value) {}
static ConfigOptionType static_type() { return coBool; }
ConfigOptionType type() const override { return static_type(); }
bool getBool() const override { return this->value; }
ConfigOption* clone() const override { return new ConfigOptionBool(*this); }
ConfigOptionBool& operator=(const ConfigOption *opt) { this->set(opt); return *this; }
bool operator==(const ConfigOptionBool &rhs) const throw() { return this->value == rhs.value; }
bool operator< (const ConfigOptionBool &rhs) const throw() { return int(this->value) < int(rhs.value); }
std::string serialize() const override
{
return std::string(this->value ? "1" : "0");
}
bool deserialize(const std::string &str, bool append = false) override
{
UNUSED(append);
if (str == "1") {
this->value = true;
return true;
}
if (str == "0") {
this->value = false;
return true;
}
return false;
}
private:
friend class cereal::access;
template<class Archive> void serialize(Archive &ar) { ar(cereal::base_class<ConfigOptionSingle<bool>>(this)); }
};
3.5.7 ConfigOptionEnum
template <class T>
class ConfigOptionEnum : public ConfigOptionSingle<T>
{
public:
// by default, use the first value (0) of the T enum type
ConfigOptionEnum() : ConfigOptionSingle<T>(static_cast<T>(0)) {}
explicit ConfigOptionEnum(T _value) : ConfigOptionSingle<T>(_value) {}
static ConfigOptionType static_type() { return coEnum; }
ConfigOptionType type() const override { return static_type(); }
ConfigOption* clone() const override { return new ConfigOptionEnum<T>(*this); }
ConfigOptionEnum<T>& operator=(const ConfigOption *opt) { this->set(opt); return *this; }
bool operator==(const ConfigOptionEnum<T> &rhs) const throw() { return this->value == rhs.value; }
bool operator< (const ConfigOptionEnum<T> &rhs) const throw() { return int(this->value) < int(rhs.value); }
int getInt() const override { return (int)this->value; }
void setInt(int val) override { this->value = T(val); }
bool operator==(const ConfigOption &rhs) const override
{
if (rhs.type() != this->type())
throw ConfigurationError("ConfigOptionEnum<T>: Comparing incompatible types");
// rhs could be of the following type: ConfigOptionEnumGeneric or ConfigOptionEnum<T>
return this->value == (T)rhs.getInt();
}
void set(const ConfigOption *rhs) override {
if (rhs->type() != this->type())
throw ConfigurationError("ConfigOptionEnum<T>: Assigning an incompatible type");
// rhs could be of the following type: ConfigOptionEnumGeneric or ConfigOptionEnum<T>
this->value = (T)rhs->getInt();
}
std::string serialize() const override
{
const t_config_enum_names& names = ConfigOptionEnum<T>::get_enum_names();
assert(static_cast<int>(this->value) < int(names.size()));
return names[static_cast<int>(this->value)];
}
bool deserialize(const std::string &str, bool append = false) override
{
UNUSED(append);
return from_string(str, this->value);
}
static bool has(T value)
{
for (const auto &kvp : ConfigOptionEnum<T>::get_enum_values())
if (kvp.second == value)
return true;
return false;
}
// Map from an enum name to an enum integer value.
static const t_config_enum_names& get_enum_names();
// Map from an enum name to an enum integer value.
static const t_config_enum_values& get_enum_values();
static bool from_string(const std::string &str, T &value)
{
const t_config_enum_values &enum_keys_map = ConfigOptionEnum<T>::get_enum_values();
auto it = enum_keys_map.find(str);
if (it == enum_keys_map.end())
return false;
value = static_cast<T>(it->second);
return true;
}
};
3.6 由ConfigOptionVector派生的类
3.6.1 ConfigOptionFloatsTempl
可直接使用ConfigOptionFloats和ConfigOptionFloatsNullable
template<bool NULLABLE>
class ConfigOptionFloatsTempl : public ConfigOptionVector<double>
{
public:
ConfigOptionFloatsTempl() : ConfigOptionVector<double>() {}
explicit ConfigOptionFloatsTempl(size_t n, double value) : ConfigOptionVector<double>(n, value) {}
explicit ConfigOptionFloatsTempl(std::initializer_list<double> il) : ConfigOptionVector<double>(std::move(il)) {}
explicit ConfigOptionFloatsTempl(const std::vector<double> &vec) : ConfigOptionVector<double>(vec) {}
explicit ConfigOptionFloatsTempl(std::vector<double> &&vec) : ConfigOptionVector<double>(std::move(vec)) {}
static ConfigOptionType static_type() { return coFloats; }
ConfigOptionType type() const override { return static_type(); }
ConfigOption* clone() const override { return new ConfigOptionFloatsTempl(*this); }
bool operator==(const ConfigOptionFloatsTempl &rhs) const throw() { return vectors_equal(this->values, rhs.values); }
bool operator< (const ConfigOptionFloatsTempl &rhs) const throw() { return vectors_lower(this->values, rhs.values); }
bool operator==(const ConfigOption &rhs) const override {
if (rhs.type() != this->type())
throw ConfigurationError("ConfigOptionFloatsTempl: Comparing incompatible types");
assert(dynamic_cast<const ConfigOptionVector<double>*>(&rhs));
return vectors_equal(this->values, static_cast<const ConfigOptionVector<double>*>(&rhs)->values);
}
// Could a special "nil" value be stored inside the vector, indicating undefined value?
bool nullable() const override { return NULLABLE; }
// Special "nil" value to be stored into the vector if this->supports_nil().
static double nil_value() { return std::numeric_limits<double>::quiet_NaN(); }
// A scalar is nil, or all values of a vector are nil.
bool is_nil() const override { for (auto v : this->values) if (! std::isnan(v)) return false; return true; }
bool is_nil(size_t idx) const override { return std::isnan(this->values[idx]); }
std::string serialize() const override
{
std::ostringstream ss;
for (const double &v : this->values) {
if (&v != &this->values.front())
ss << ",";
serialize_single_value(ss, v);
}
return ss.str();
}
std::vector<std::string> vserialize() const override
{
std::vector<std::string> vv;
vv.reserve(this->values.size());
for (const double v : this->values) {
std::ostringstream ss;
serialize_single_value(ss, v);
vv.push_back(ss.str());
}
return vv;
}
bool deserialize(const std::string &str, bool append = false) override
{
if (! append)
this->values.clear();
std::istringstream is(str);
std::string item_str;
while (std::getline(is, item_str, ',')) {
boost::trim(item_str);
if (item_str == "nil") {
if (NULLABLE)
this->values.push_back(nil_value());
else
throw ConfigurationError("Deserializing nil into a non-nullable object");
} else {
std::istringstream iss(item_str);
double value;
iss >> value;
this->values.push_back(value);
}
}
return true;
}
ConfigOptionFloatsTempl& operator=(const ConfigOption *opt)
{
this->set(opt);
return *this;
}
protected:
void serialize_single_value(std::ostringstream &ss, const double v) const {
if (std::isfinite(v))
ss << v;
else if (std::isnan(v)) {
if (NULLABLE)
ss << "nil";
else
throw ConfigurationError("Serializing NaN");
} else
throw ConfigurationError("Serializing invalid number");
}
static bool vectors_equal(const std::vector<double> &v1, const std::vector<double> &v2) {
if (NULLABLE) {
if (v1.size() != v2.size())
return false;
for (auto it1 = v1.begin(), it2 = v2.begin(); it1 != v1.end(); ++ it1, ++ it2)
if (! ((std::isnan(*it1) && std::isnan(*it2)) || *it1 == *it2))
return false;
return true;
} else
// Not supporting nullable values, the default vector compare is cheaper.
return v1 == v2;
}
static bool vectors_lower(const std::vector<double> &v1, const std::vector<double> &v2) {
if (NULLABLE) {
for (auto it1 = v1.begin(), it2 = v2.begin(); it1 != v1.end() && it2 != v2.end(); ++ it1, ++ it2) {
auto null1 = int(std::isnan(*it1));
auto null2 = int(std::isnan(*it2));
return (null1 < null2) || (null1 == null2 && *it1 < *it2);
}
return v1.size() < v2.size();
} else
// Not supporting nullable values, the default vector compare is cheaper.
return v1 < v2;
}
private:
friend class cereal::access;
template<class Archive> void serialize(Archive &ar) { ar(cereal::base_class<ConfigOptionVector<double>>(this)); }
};
using ConfigOptionFloats = ConfigOptionFloatsTempl<false>;
using ConfigOptionFloatsNullable = ConfigOptionFloatsTempl<true>;
3.6.2 ConfigOptionIntsTempl
可直接使用ConfigOptionInts和ConfigOptionIntsNullable
template<bool NULLABLE>
class ConfigOptionIntsTempl : public ConfigOptionVector<int>
{
public:
ConfigOptionIntsTempl() : ConfigOptionVector<int>() {}
explicit ConfigOptionIntsTempl(size_t n, int value) : ConfigOptionVector<int>(n, value) {}
explicit ConfigOptionIntsTempl(std::initializer_list<int> il) : ConfigOptionVector<int>(std::move(il)) {}
explicit ConfigOptionIntsTempl(const std::vector<int> &vec) : ConfigOptionVector<int>(vec) {}
explicit ConfigOptionIntsTempl(std::vector<int> &&vec) : ConfigOptionVector<int>(std::move(vec)) {}
static

最低0.47元/天 解锁文章
1210

被折叠的 条评论
为什么被折叠?



