12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300 |
- #ifndef slic3r_Config_hpp_
- #define slic3r_Config_hpp_
- #include <assert.h>
- #include <map>
- #include <climits>
- #include <cstdio>
- #include <cstdlib>
- #include <functional>
- #include <iostream>
- #include <stdexcept>
- #include <string>
- #include <vector>
- #include "libslic3r.h"
- #include "clonable_ptr.hpp"
- #include "Exception.hpp"
- #include "Point.hpp"
- #include <boost/algorithm/string/predicate.hpp>
- #include <boost/algorithm/string/trim.hpp>
- #include <boost/format/format_fwd.hpp>
- #include <boost/property_tree/ptree_fwd.hpp>
- #include <cereal/access.hpp>
- #include <cereal/types/base_class.hpp>
- namespace Slic3r {
- // Name of the configuration option.
- typedef std::string t_config_option_key;
- typedef std::vector<std::string> t_config_option_keys;
- extern std::string escape_string_cstyle(const std::string &str);
- extern std::string escape_strings_cstyle(const std::vector<std::string> &strs);
- extern bool unescape_string_cstyle(const std::string &str, std::string &out);
- extern bool unescape_strings_cstyle(const std::string &str, std::vector<std::string> &out);
- extern std::string escape_ampersand(const std::string& str);
- enum OptionCategory : int
- {
- none,
- perimeter,
- slicing,
- infill,
- ironing,
- skirtBrim,
- support,
- speed,
- width,
- extruders,
- output,
- notes,
- dependencies,
- filament,
- cooling,
- advanced,
- filoverride,
- customgcode,
-
- general,
- limits,
- mmsetup,
- firmware,
- pad,
- padSupp,
- wipe,
- hollowing,
- milling_extruders,
- milling,
- };
- std::string toString(OptionCategory opt);
- namespace ConfigHelpers {
- inline bool looks_like_enum_value(std::string value)
- {
- boost::trim(value);
- if (value.empty() || value.size() > 64 || ! isalpha(value.front()))
- return false;
- for (const char c : value)
- if (! (isalnum(c) || c == '_' || c == '-'))
- return false;
- return true;
- }
- inline bool enum_looks_like_true_value(std::string value) {
- boost::trim(value);
- return boost::iequals(value, "enabled") || boost::iequals(value, "on");
- }
- enum class DeserializationSubstitution {
- Disabled,
- DefaultsToFalse,
- DefaultsToTrue
- };
- enum class DeserializationResult {
- Loaded,
- Substituted,
- Failed,
- };
- };
- // Base for all exceptions thrown by the configuration layer.
- class ConfigurationError : public Slic3r::RuntimeError {
- public:
- using RuntimeError::RuntimeError;
- };
- // Specialization of std::exception to indicate that an unknown config option has been encountered.
- class UnknownOptionException : public ConfigurationError {
- public:
- UnknownOptionException() :
- ConfigurationError("Unknown option exception") {}
- UnknownOptionException(const std::string &opt_key) :
- ConfigurationError(std::string("Unknown option exception: ") + opt_key) {}
- };
- // Indicate that the ConfigBase derived class does not provide config definition (the method def() returns null).
- class NoDefinitionException : public ConfigurationError
- {
- public:
- NoDefinitionException() :
- ConfigurationError("No definition exception") {}
- NoDefinitionException(const std::string &opt_key) :
- ConfigurationError(std::string("No definition exception: ") + opt_key) {}
- };
- // a bit more specific than a runtime_error
- class ConfigurationException : public std::runtime_error
- {
- public:
- ConfigurationException() :
- std::runtime_error("Configuration exception") {}
- ConfigurationException(const std::string &opt_key) :
- std::runtime_error(std::string("Configuration exception: ") + opt_key) {}
- };
- // Indicate that an unsupported accessor was called on a config option.
- class BadOptionTypeException : public ConfigurationError
- {
- public:
- BadOptionTypeException() : ConfigurationError("Bad option type exception") {}
- BadOptionTypeException(const std::string &message) : ConfigurationError(message) {}
- BadOptionTypeException(const char* message) : ConfigurationError(message) {}
- };
- // Indicate that an option has been deserialized from an invalid value.
- class BadOptionValueException : public ConfigurationError
- {
- public:
- BadOptionValueException() : ConfigurationError("Bad option value exception") {}
- BadOptionValueException(const std::string &message) : ConfigurationError(message) {}
- BadOptionValueException(const char* message) : ConfigurationError(message) {}
- };
- // Type of a configuration value.
- enum ConfigOptionType : uint16_t{
- 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 & flow ratio.
- 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,
- };
- enum ConfigOptionMode {
- comSimple = 0,
- comAdvanced,
- comExpert
- };
- enum PrinterTechnology : uint8_t
- {
- // Fused Filament Fabrication
- ptFFF = 1 << 0,
- // Stereolitography
- ptSLA = 1 << 1,
- // Selective Laser-Sintering
- ptSLS = 1 << 2,
- // CNC
- ptMill = 1 << 3,
- // Laser engraving
- ptLaser = 1 << 4,
- // Any technology, useful for parameters compatible with both ptFFF and ptSLA
- ptAny = ptFFF | ptSLA | ptSLS | ptMill | ptLaser,
- // Unknown, useful for command line processing
- ptUnknown = 1 << 7
- };
- inline PrinterTechnology operator|(PrinterTechnology a, PrinterTechnology b) {
- return static_cast<PrinterTechnology>(static_cast<uint8_t>(a) | static_cast<uint8_t>(b));
- }
- inline PrinterTechnology operator&(PrinterTechnology a, PrinterTechnology b) {
- return static_cast<PrinterTechnology>(static_cast<uint8_t>(a)& static_cast<uint8_t>(b));
- }
- inline PrinterTechnology operator|=(PrinterTechnology& a, PrinterTechnology b) {
- a = a | b; return a;
- }
- inline PrinterTechnology operator&=(PrinterTechnology& a, PrinterTechnology b) {
- a = a & b; return a;
- }
- ///
- enum OutputFormat : uint16_t
- {
- ofMaskedCWS = 1 << 0,
- ofSL1 = 1 << 1,
- ofGCode = 1 << 2,
- ofUnknown = 1 << 15
- };
- inline OutputFormat operator|(OutputFormat a, OutputFormat b) {
- return static_cast<OutputFormat>(static_cast<uint8_t>(a) | static_cast<uint8_t>(b));
- }
- inline OutputFormat operator&(OutputFormat a, OutputFormat b) {
- return static_cast<OutputFormat>(static_cast<uint8_t>(a)& static_cast<uint8_t>(b));
- }
- inline OutputFormat operator|=(OutputFormat& a, OutputFormat b) {
- a = a | b; return a;
- }
- inline OutputFormat operator&=(OutputFormat& a, OutputFormat b) {
- a = a & b; return a;
- }
- enum ForwardCompatibilitySubstitutionRule
- {
- // Disable susbtitution, throw exception if an option value is not recognized.
- Disable,
- // Enable substitution of an unknown option value with default. Log the substitution.
- Enable,
- // Enable substitution of an unknown option value with default. Don't log the substitution.
- EnableSilent,
- // Enable substitution of an unknown option value with default. Log substitutions in user profiles, don't log substitutions in system profiles.
- EnableSystemSilent,
- // Enable silent substitution of an unknown option value with default when loading user profiles. Throw on an unknown option value in a system profile.
- EnableSilentDisableSystem,
- };
- class ConfigOption;
- class ConfigOptionDef;
- // For forward definition of ConfigOption in ConfigOptionUniquePtr, we have to define a custom deleter.
- struct ConfigOptionDeleter { void operator()(ConfigOption* p); };
- using ConfigOptionUniquePtr = std::unique_ptr<ConfigOption, ConfigOptionDeleter>;
- // When parsing a configuration value, if the old_value is not understood by this PrusaSlicer version,
- // it is being substituted with some default value that this PrusaSlicer could work with.
- // This structure serves to inform the user about the substitutions having been done during file import.
- struct ConfigSubstitution {
- const ConfigOptionDef *opt_def { nullptr };
- std::string old_value;
- ConfigOptionUniquePtr new_value;
- ConfigSubstitution() = default;
- ConfigSubstitution(const ConfigOptionDef* def, std::string old, ConfigOptionUniquePtr&& new_v) : opt_def(def), old_value(old), new_value(std::move(new_v)) {}
- };
- using ConfigSubstitutions = std::vector<ConfigSubstitution>;
- // Filled in by ConfigBase::set_deserialize_raw(), which based on "rule" either bails out
- // or performs substitutions when encountering an unknown configuration value.
- struct ConfigSubstitutionContext
- {
- ConfigSubstitutionContext(ForwardCompatibilitySubstitutionRule rl) : rule(rl) {}
- bool empty() const throw() { return substitutions.empty(); }
- ForwardCompatibilitySubstitutionRule rule;
- ConfigSubstitutions substitutions;
- };
- // A generic value of a configuration option.
- class ConfigOption {
- public:
- // if true, this option doesn't need to be saved, it's a computed value from an other configOption.
- // uint32_t because macos crash if it's a bool. and it doesn't change the size of the object because of alignment.
- uint32_t flags;
- enum FlagsConfigOption : uint32_t {
- FCO_PHONY = 1,
- FCO_EXTRUDER_ARRAY = 1 << 1,
- FCO_PLACEHOLDER_TEMP = 1 << 2,
- };
- ConfigOption() : flags(uint32_t(0)) {}
- ConfigOption(bool phony) : flags(phony ? uint32_t(FlagsConfigOption::FCO_PHONY) : uint32_t(0)) {}
- 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 int32_t 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(int32_t /* 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); }
- 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; }
- bool is_phony() const { return (flags & FCO_PHONY) != 0; }
- void set_phony(bool phony) { if (phony) this->flags |= FCO_PHONY; else this->flags &= uint8_t(0xFF ^ FCO_PHONY); }
- // 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;
- }
- private:
- friend class cereal::access;
- template<class Archive> void serialize(Archive& ar) { ar(this->flags); }
- };
- typedef ConfigOption* ConfigOptionPtr;
- typedef const ConfigOption* ConfigOptionConstPtr;
- // Value of a single valued option (bool, int, float, string, point, enum)
- template <class T>
- class ConfigOptionSingle : public ConfigOption {
- public:
- T value;
- explicit ConfigOptionSingle(T value) : value(value) {}
- explicit ConfigOptionSingle(T value, bool phony) : ConfigOption(phony), value(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;
- this->flags = rhs->flags;
- }
- 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 { return this->value == rhs; }
- bool operator!=(const T &rhs) const { return this->value != rhs; }
- private:
- friend class cereal::access;
- template<class Archive> void serialize(Archive & ar) { ar(this->flags); ar(this->value); }
- };
- // Value of a vector valued option (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;
- // Get if the size of this vector is/should be the same as nozzle_diameter
- bool is_extruder_size() const { return (flags & FCO_EXTRUDER_ARRAY) != 0; }
- ConfigOptionVectorBase* set_is_extruder_size(bool is_extruder_size) {
- if (is_extruder_size) this->flags |= FCO_EXTRUDER_ARRAY; else this->flags &= uint8_t(0xFF ^ FCO_EXTRUDER_ARRAY);
- return this;
- }
- virtual double getFloat(int idx) const { throw BadOptionTypeException("Calling ConfigOption::getFloat(idx) on a non-numeric arrray ConfigOptionVectorBase"); }
- // 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); }
- };
- // Value of a vector valued option (bools, ints, floats, strings, points), template
- template <class T>
- class ConfigOptionVector : public ConfigOptionVectorBase
- {
- public:
- ConfigOptionVector() {}
- explicit ConfigOptionVector(const T& default_val) : default_value(default_val) {}
- 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;
- T default_value;
-
- 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;
- this->flags = rhs->flags;
- }
- // 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.empty()? default_value : 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.
- 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)
- this->values.resize(n, this->default_value);
- if (opt_default->type() != this->type())
- throw ConfigurationError("ConfigOptionVector::resize(): Extending with an incompatible type.");
- if(static_cast<const ConfigOptionVector<T>*>(opt_default)->values.empty())
- this->values.resize(n, this->default_value);
- else
- this->values.resize(n, static_cast<const ConfigOptionVector<T>*>(opt_default)->values.front());
- } 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 { return this->values == rhs; }
- bool operator!=(const std::vector<T> &rhs) const { return this->values != rhs; }
- // 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 i = 0;
- size_t cnt = std::min(this->size(), rhs_vec->size());
- bool modified = false;
- for (; i < cnt; ++ i)
- if (! rhs_vec->is_nil(i) && this->values[i] != rhs_vec->values[i]) {
- this->values[i] = rhs_vec->values[i];
- modified = true;
- }
- for (; i < rhs_vec->size(); ++ i)
- if (! rhs_vec->is_nil(i)) {
- if (this->values.empty())
- this->values.resize(i + 1);
- else
- this->values.resize(i + 1, this->values.front());
- this->values[i] = rhs_vec->values[i];
- modified = true;
- }
- return modified;
- }
- private:
- friend class cereal::access;
- template<class Archive> void serialize(Archive & ar) { ar(this->flags); ar(this->values); }
- };
- class ConfigOptionFloat : public ConfigOptionSingle<double>
- {
- public:
- ConfigOptionFloat() : ConfigOptionSingle<double>(0) {}
- explicit ConfigOptionFloat(double _value) : ConfigOptionSingle<double>(_value) {}
- explicit ConfigOptionFloat(double _value, bool _phony) : ConfigOptionSingle<double>(_value, _phony) {}
- 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 { 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)); }
- };
- template<bool NULLABLE>
- class ConfigOptionFloatsTempl : public ConfigOptionVector<double>
- {
- public:
- ConfigOptionFloatsTempl() : ConfigOptionVector<double>() {}
- explicit ConfigOptionFloatsTempl(double default_value) : ConfigOptionVector<double>(default_value) {}
- 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 { return vectors_equal(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]); }
- virtual double getFloat(int idx) const override { return 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;
- }
- 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>;
- class ConfigOptionInt : public ConfigOptionSingle<int32_t>
- {
- public:
- ConfigOptionInt() : ConfigOptionSingle<int32_t>(0) {}
- explicit ConfigOptionInt(int32_t value) : ConfigOptionSingle<int32_t>(value) {}
- explicit ConfigOptionInt(double _value) : ConfigOptionSingle<int32_t>(int32_t(floor(_value + 0.5))) {}
-
- static ConfigOptionType static_type() { return coInt; }
- ConfigOptionType type() const override { return static_type(); }
- int32_t getInt() const override { return this->value; }
- void setInt(int32_t val) override { this->value = val; }
- ConfigOption* clone() const override { return new ConfigOptionInt(*this); }
- bool operator==(const ConfigOptionInt &rhs) const { 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<int32_t>>(this)); }
- };
- template<bool NULLABLE>
- class ConfigOptionIntsTempl : public ConfigOptionVector<int32_t>
- {
- public:
- ConfigOptionIntsTempl() : ConfigOptionVector<int32_t>() {}
- explicit ConfigOptionIntsTempl(int32_t default_value) : ConfigOptionVector<int32_t>(default_value) {}
- explicit ConfigOptionIntsTempl(size_t n, int32_t value) : ConfigOptionVector<int32_t>(n, value) {}
- explicit ConfigOptionIntsTempl(std::initializer_list<int32_t> il) : ConfigOptionVector<int32_t>(std::move(il)) {}
- static ConfigOptionType static_type() { return coInts; }
- ConfigOptionType type() const override { return static_type(); }
- ConfigOption* clone() const override { return new ConfigOptionIntsTempl(*this); }
- ConfigOptionIntsTempl& operator=(const ConfigOption *opt) { this->set(opt); return *this; }
- bool operator==(const ConfigOptionIntsTempl &rhs) const { return this->values == 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 int32_t nil_value() { return std::numeric_limits<int32_t>::max(); }
- // A scalar is nil, or all values of a vector are nil.
- bool is_nil() const override { for (auto v : this->values) if (v != nil_value()) return false; return true; }
- bool is_nil(size_t idx) const override { return this->values[idx] == nil_value(); }
- virtual double getFloat(int idx) const override { return values[idx]; }
- std::string serialize() const override
- {
- std::ostringstream ss;
- for (const int32_t &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 int32_t 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);
- int32_t value;
- iss >> value;
- this->values.push_back(value);
- }
- }
- return true;
- }
- private:
- void serialize_single_value(std::ostringstream &ss, const int32_t v) const {
- if (v == nil_value()) {
- if (NULLABLE)
- ss << "nil";
- else
- throw ConfigurationError("Serializing NaN");
- } else
- ss << v;
- }
- friend class cereal::access;
- template<class Archive> void serialize(Archive &ar) { ar(cereal::base_class<ConfigOptionVector<int32_t>>(this)); }
- };
- using ConfigOptionInts = ConfigOptionIntsTempl<false>;
- using ConfigOptionIntsNullable = ConfigOptionIntsTempl<true>;
- class ConfigOptionString : public ConfigOptionSingle<std::string>
- {
- public:
- ConfigOptionString() : ConfigOptionSingle<std::string>("") {}
- explicit ConfigOptionString(const std::string &value) : ConfigOptionSingle<std::string>(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 { 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)); }
- };
- // semicolon-separated strings
- class ConfigOptionStrings : public ConfigOptionVector<std::string>
- {
- public:
- ConfigOptionStrings() : ConfigOptionVector<std::string>() {}
- explicit ConfigOptionStrings(const std::string& value) : ConfigOptionVector<std::string>(value) {}
- explicit ConfigOptionStrings(size_t n, const std::string& value) : ConfigOptionVector<std::string>(n, value) {}
- explicit ConfigOptionStrings(const std::vector<std::string> &values) : ConfigOptionVector<std::string>(values) {}
- explicit ConfigOptionStrings(std::vector<std::string> &&values) : ConfigOptionVector<std::string>(std::move(values)) {}
- explicit ConfigOptionStrings(std::initializer_list<std::string> il) : ConfigOptionVector<std::string>(std::move(il)) {}
- static ConfigOptionType static_type() { return coStrings; }
- ConfigOptionType type() const override { return static_type(); }
- ConfigOption* clone() const override { return new ConfigOptionStrings(*this); }
- ConfigOptionStrings& operator=(const ConfigOption *opt) { this->set(opt); return *this; }
- bool operator==(const ConfigOptionStrings &rhs) const { return this->values == rhs.values; }
- bool is_nil(size_t) const override { return false; }
- std::string serialize() const override
- {
- return escape_strings_cstyle(this->values);
- }
-
- std::vector<std::string> vserialize() const override
- {
- return this->values;
- }
-
- bool deserialize(const std::string &str, bool append = false) override
- {
- if (! append)
- this->values.clear();
- return unescape_strings_cstyle(str, this->values);
- }
- private:
- friend class cereal::access;
- template<class Archive> void serialize(Archive &ar) { ar(cereal::base_class<ConfigOptionVector<std::string>>(this)); }
- };
- class ConfigOptionPercent : public ConfigOptionFloat
- {
- public:
- ConfigOptionPercent() : ConfigOptionFloat(0) {}
- explicit ConfigOptionPercent(double _value) : ConfigOptionFloat(_value) {}
- explicit ConfigOptionPercent(double _value, bool _phony) : ConfigOptionFloat(_value, _phony) {}
-
- static ConfigOptionType static_type() { return coPercent; }
- ConfigOptionType type() const override { return static_type(); }
- ConfigOption* clone() const override { return new ConfigOptionPercent(*this); }
- ConfigOptionPercent& operator=(const ConfigOption *opt) { this->set(opt); return *this; }
- bool operator==(const ConfigOptionPercent &rhs) const { return this->value == rhs.value; }
- double get_abs_value(double ratio_over) const { return ratio_over * this->value / 100.; }
-
- std::string serialize() const override
- {
- std::ostringstream ss;
- ss << this->value;
- std::string s(ss.str());
- s += "%";
- return s;
- }
-
- bool deserialize(const std::string &str, bool append = false) override
- {
- UNUSED(append);
- // don't try to parse the trailing % since it's optional
- std::istringstream iss(str);
- iss >> this->value;
- return !iss.fail();
- }
- private:
- friend class cereal::access;
- template<class Archive> void serialize(Archive &ar) { ar(cereal::base_class<ConfigOptionFloat>(this)); }
- };
- template<bool NULLABLE>
- class ConfigOptionPercentsTempl : public ConfigOptionFloatsTempl<NULLABLE>
- {
- public:
- ConfigOptionPercentsTempl() : ConfigOptionFloatsTempl<NULLABLE>() {}
- explicit ConfigOptionPercentsTempl(double default_value) : ConfigOptionFloatsTempl<NULLABLE>(default_value) {}
- explicit ConfigOptionPercentsTempl(size_t n, double value) : ConfigOptionFloatsTempl<NULLABLE>(n, value) {}
- explicit ConfigOptionPercentsTempl(std::initializer_list<double> il) : ConfigOptionFloatsTempl<NULLABLE>(std::move(il)) {}
- explicit ConfigOptionPercentsTempl(const std::vector<double>& vec) : ConfigOptionFloatsTempl<NULLABLE>(vec) {}
- explicit ConfigOptionPercentsTempl(std::vector<double>&& vec) : ConfigOptionFloatsTempl<NULLABLE>(std::move(vec)) {}
- static ConfigOptionType static_type() { return coPercents; }
- ConfigOptionType type() const override { return static_type(); }
- ConfigOption* clone() const override { return new ConfigOptionPercentsTempl(*this); }
- ConfigOptionPercentsTempl& operator=(const ConfigOption *opt) { this->set(opt); return *this; }
- bool operator==(const ConfigOptionPercentsTempl &rhs) const { return this->values == rhs.values; }
- double get_abs_value(size_t i, double ratio_over) const { return this->is_nil(i) ? 0 : ratio_over * this->get_at(i) / 100; }
- std::string serialize() const override
- {
- std::ostringstream ss;
- for (const double &v : this->values) {
- if (&v != &this->values.front())
- ss << ",";
- this->serialize_single_value(ss, v);
- if (! std::isnan(v))
- ss << "%";
- }
- std::string str = ss.str();
- return 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;
- this->serialize_single_value(ss, v);
- if (! std::isnan(v))
- ss << "%";
- vv.push_back(ss.str());
- }
- return vv;
- }
- // The float's deserialize function shall ignore the trailing optional %.
- // bool deserialize(const std::string &str, bool append = false) override;
- private:
- friend class cereal::access;
- template<class Archive> void serialize(Archive &ar) { ar(cereal::base_class<ConfigOptionFloatsTempl<NULLABLE>>(this)); }
- };
- using ConfigOptionPercents = ConfigOptionPercentsTempl<false>;
- using ConfigOptionPercentsNullable = ConfigOptionPercentsTempl<true>;
- class ConfigOptionFloatOrPercent : public ConfigOptionPercent
- {
- public:
- bool percent;
- ConfigOptionFloatOrPercent() : ConfigOptionPercent(0), percent(false) {}
- explicit ConfigOptionFloatOrPercent(double _value, bool _percent) : ConfigOptionPercent(_value), percent(_percent) {}
- explicit ConfigOptionFloatOrPercent(double _value, bool _percent, bool _phony) : ConfigOptionPercent(_value, _phony), percent(_percent) {}
- static ConfigOptionType static_type() { return coFloatOrPercent; }
- ConfigOptionType type() const override { return static_type(); }
- ConfigOption* clone() const override { return new ConfigOptionFloatOrPercent(*this); }
- ConfigOptionFloatOrPercent& operator=(const ConfigOption* opt) { this->set(opt); return *this; }
- bool operator==(const ConfigOption &rhs) const override
- {
- if (rhs.type() != this->type())
- throw ConfigurationError("ConfigOptionFloatOrPercent: Comparing incompatible types");
- assert(dynamic_cast<const ConfigOptionFloatOrPercent*>(&rhs));
- return *this == *static_cast<const ConfigOptionFloatOrPercent*>(&rhs);
- }
- bool operator==(const ConfigOptionFloatOrPercent &rhs) const
- { return this->value == rhs.value && this->percent == rhs.percent; }
- double get_abs_value(double ratio_over) const
- { return this->percent ? (ratio_over * this->value / 100) : this->value; }
- void set(const ConfigOption *rhs) override {
- if (rhs->type() != this->type())
- throw ConfigurationError("ConfigOptionFloatOrPercent: Assigning an incompatible type");
- assert(dynamic_cast<const ConfigOptionFloatOrPercent*>(rhs));
- *this = *static_cast<const ConfigOptionFloatOrPercent*>(rhs);
- }
- std::string serialize() const override
- {
- std::ostringstream ss;
- ss << this->value;
- std::string s(ss.str());
- if (this->percent) s += "%";
- return s;
- }
-
- bool deserialize(const std::string &str, bool append = false) override
- {
- UNUSED(append);
- this->percent = str.find_first_of("%") != std::string::npos;
- std::istringstream iss(str);
- iss >> this->value;
- return !iss.fail();
- }
- private:
- friend class cereal::access;
- template<class Archive> void serialize(Archive &ar) { ar(cereal::base_class<ConfigOptionPercent>(this), percent); }
- };
- struct FloatOrPercent
- {
- public:
- double value;
- bool percent;
- double get_abs_value(double ratio) const { return percent ? value * ratio : value; }
- private:
- friend class cereal::access;
- template<class Archive> void serialize(Archive & ar) {ar(this->value); ar(this->percent); }
- };
- inline bool operator==(const FloatOrPercent &l, const FloatOrPercent &r)
- {
- return l.value == r.value && l.percent == r.percent;
- }
- inline bool operator!=(const FloatOrPercent& l, const FloatOrPercent& r)
- {
- return !(l == r);
- }
- template<bool NULLABLE>
- class ConfigOptionFloatsOrPercentsTempl : public ConfigOptionVector<FloatOrPercent>
- {
- public:
- ConfigOptionFloatsOrPercentsTempl() : ConfigOptionVector<FloatOrPercent>() {}
- explicit ConfigOptionFloatsOrPercentsTempl(FloatOrPercent default_value) : ConfigOptionVector<FloatOrPercent>(default_value) {}
- explicit ConfigOptionFloatsOrPercentsTempl(size_t n, FloatOrPercent value) : ConfigOptionVector<FloatOrPercent>(n, value) {}
- explicit ConfigOptionFloatsOrPercentsTempl(std::initializer_list<FloatOrPercent> il) : ConfigOptionVector<FloatOrPercent>(std::move(il)) {}
- explicit ConfigOptionFloatsOrPercentsTempl(const std::vector<FloatOrPercent> &vec) : ConfigOptionVector<FloatOrPercent>(vec) {}
- explicit ConfigOptionFloatsOrPercentsTempl(std::vector<FloatOrPercent> &&vec) : ConfigOptionVector<FloatOrPercent>(std::move(vec)) {}
- static ConfigOptionType static_type() { return coFloatsOrPercents; }
- ConfigOptionType type() const override { return static_type(); }
- ConfigOption* clone() const override { return new ConfigOptionFloatsOrPercentsTempl(*this); }
- bool operator==(const ConfigOptionFloatsOrPercentsTempl &rhs) const { return vectors_equal(this->values, rhs.values); }
- bool operator==(const ConfigOption &rhs) const override {
- if (rhs.type() != this->type())
- throw ConfigurationError("ConfigOptionFloatsOrPercentsTempl: Comparing incompatible types");
- assert(dynamic_cast<const ConfigOptionVector<FloatOrPercent>*>(&rhs));
- return vectors_equal(this->values, static_cast<const ConfigOptionVector<FloatOrPercent>*>(&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 FloatOrPercent nil_value() { return { std::numeric_limits<double>::quiet_NaN(), false }; }
- // 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.value)) return false; return true; }
- bool is_nil(size_t idx) const override { return std::isnan(this->values[idx].value); }
- double get_abs_value(size_t i, double ratio_over) const {
- if (this->is_nil(i)) return 0;
- const FloatOrPercent& data = this->get_at(i);
- if (data.percent) return ratio_over * data.value / 100;
- return data.value;
- }
- std::string serialize() const override
- {
- std::ostringstream ss;
- for (const FloatOrPercent &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 FloatOrPercent &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 {
- bool percent = item_str.find_first_of("%") != std::string::npos;
- std::istringstream iss(item_str);
- double value;
- iss >> value;
- this->values.push_back({ value, percent });
- }
- }
- return true;
- }
- ConfigOptionFloatsOrPercentsTempl& operator=(const ConfigOption *opt)
- {
- this->set(opt);
- return *this;
- }
- protected:
- void serialize_single_value(std::ostringstream &ss, const FloatOrPercent &v) const {
- if (std::isfinite(v.value)) {
- ss << v.value;
- if (v.percent)
- ss << "%";
- } else if (std::isnan(v.value)) {
- if (NULLABLE)
- ss << "nil";
- else
- throw ConfigurationError("Serializing NaN");
- } else
- throw ConfigurationError("Serializing invalid number");
- }
- static bool vectors_equal(const std::vector<FloatOrPercent> &v1, const std::vector<FloatOrPercent> &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->value) && std::isnan(it2->value)) || *it1 == *it2))
- return false;
- return true;
- } 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<FloatOrPercent>>(this)); }
- };
- using ConfigOptionFloatsOrPercents = ConfigOptionFloatsOrPercentsTempl<false>;
- using ConfigOptionFloatsOrPercentsNullable = ConfigOptionFloatsOrPercentsTempl<true>;
- 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 { 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)); }
- };
- class ConfigOptionPoints : public ConfigOptionVector<Vec2d>
- {
- public:
- ConfigOptionPoints() : ConfigOptionVector<Vec2d>() {}
- explicit ConfigOptionPoints(const Vec2d& value) : ConfigOptionVector<Vec2d>(value) {}
- explicit ConfigOptionPoints(size_t n, const Vec2d& value) : ConfigOptionVector<Vec2d>(n, value) {}
- explicit ConfigOptionPoints(std::initializer_list<Vec2d> il) : ConfigOptionVector<Vec2d>(std::move(il)) {}
- explicit ConfigOptionPoints(const std::vector<Vec2d> &values) : ConfigOptionVector<Vec2d>(values) {}
- static ConfigOptionType static_type() { return coPoints; }
- ConfigOptionType type() const override { return static_type(); }
- ConfigOption* clone() const override { return new ConfigOptionPoints(*this); }
- ConfigOptionPoints& operator=(const ConfigOption *opt) { this->set(opt); return *this; }
- bool operator==(const ConfigOptionPoints &rhs) const { return this->values == rhs.values; }
- bool is_nil(size_t) const override { return false; }
- std::string serialize() const override
- {
- std::ostringstream ss;
- for (Pointfs::const_iterator it = this->values.begin(); it != this->values.end(); ++it) {
- if (it - this->values.begin() != 0) ss << ",";
- ss << (*it)(0);
- ss << "x";
- ss << (*it)(1);
- }
- return ss.str();
- }
-
- std::vector<std::string> vserialize() const override
- {
- std::vector<std::string> vv;
- for (Pointfs::const_iterator it = this->values.begin(); it != this->values.end(); ++it) {
- std::ostringstream ss;
- ss << *it;
- 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 point_str;
- while (std::getline(is, point_str, ',')) {
- Vec2d point(Vec2d::Zero());
- std::istringstream iss(point_str);
- std::string coord_str;
- if (std::getline(iss, coord_str, 'x')) {
- std::istringstream(coord_str) >> point(0);
- if (std::getline(iss, coord_str, 'x')) {
- std::istringstream(coord_str) >> point(1);
- }
- }
- this->values.push_back(point);
- }
- return true;
- }
- private:
- friend class cereal::access;
- template<class Archive> void save(Archive& archive) const {
- archive(flags);
- size_t cnt = this->values.size();
- archive(cnt);
- archive.saveBinary((const char*)this->values.data(), sizeof(Vec2d) * cnt);
- }
- template<class Archive> void load(Archive& archive) {
- archive(flags);
- size_t cnt;
- archive(cnt);
- this->values.assign(cnt, Vec2d());
- archive.loadBinary((char*)this->values.data(), sizeof(Vec2d) * cnt);
- }
- };
- 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 { return this->value == rhs.value; }
- 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) == 2 ||
- sscanf(str.data(), " %lf x %lf x %lf %c", &this->value(0), &this->value(1), &this->value(2), &dummy) == 2;
- }
- private:
- friend class cereal::access;
- template<class Archive> void serialize(Archive &ar) { ar(cereal::base_class<ConfigOptionSingle<Vec3d>>(this)); }
- };
- 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 { return this->value == 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)); }
- };
- template<bool NULLABLE>
- class ConfigOptionBoolsTempl : public ConfigOptionVector<unsigned char>
- {
- public:
- ConfigOptionBoolsTempl() : ConfigOptionVector<unsigned char>() {}
- explicit ConfigOptionBoolsTempl(size_t n, bool value) : ConfigOptionVector<unsigned char>(n, (unsigned char)value) {}
- explicit ConfigOptionBoolsTempl(std::initializer_list<bool> il) { values.reserve(il.size()); for (bool b : il) values.emplace_back((unsigned char)b); }
- explicit ConfigOptionBoolsTempl(std::initializer_list<unsigned char> il) { values.reserve(il.size()); for (unsigned char b : il) values.emplace_back(b); }
- explicit ConfigOptionBoolsTempl(const std::vector<unsigned char>& vec) : ConfigOptionVector<unsigned char>(vec) {}
- explicit ConfigOptionBoolsTempl(std::vector<unsigned char>&& vec) : ConfigOptionVector<unsigned char>(std::move(vec)) {}
- static ConfigOptionType static_type() { return coBools; }
- ConfigOptionType type() const override { return static_type(); }
- ConfigOption* clone() const override { return new ConfigOptionBoolsTempl(*this); }
- ConfigOptionBoolsTempl& operator=(const ConfigOption *opt) { this->set(opt); return *this; }
- bool operator==(const ConfigOptionBoolsTempl &rhs) const { return this->values == 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 unsigned char nil_value() { return std::numeric_limits<unsigned char>::max(); }
- // A scalar is nil, or all values of a vector are nil.
- bool is_nil() const override { for (auto v : this->values) if (v != nil_value()) return false; return true; }
- bool is_nil(size_t idx) const override { return this->values[idx] == nil_value(); }
- virtual double getFloat(int idx) const override { return values[idx] ? 1 : 0; }
- bool& get_at(size_t i) {
- assert(! this->values.empty());
- return *reinterpret_cast<bool*>(&((i < this->values.size()) ? this->values[i] : this->values.front()));
- }
- //FIXME this smells, the parent class has the method declared returning (unsigned char&).
- bool get_at(size_t i) const { return ((i < this->values.size()) ? this->values[i] : this->values.front()) != 0; }
- std::string serialize() const override
- {
- std::ostringstream ss;
- for (const unsigned char &v : this->values) {
- if (&v != &this->values.front())
- ss << ",";
- this->serialize_single_value(ss, v);
- }
- return ss.str();
- }
-
- std::vector<std::string> vserialize() const override
- {
- std::vector<std::string> vv;
- for (const unsigned char v : this->values) {
- std::ostringstream ss;
- this->serialize_single_value(ss, v);
- vv.push_back(ss.str());
- }
- return vv;
- }
- ConfigHelpers::DeserializationResult deserialize_with_substitutions(const std::string &str, bool append, ConfigHelpers::DeserializationSubstitution substitution)
- {
- if (! append)
- this->values.clear();
- std::istringstream is(str);
- std::string item_str;
- bool substituted = false;
- while (std::getline(is, item_str, ',')) {
- boost::trim(item_str);
- unsigned char new_value = 0;
- if (item_str == "nil") {
- if (NULLABLE)
- new_value = nil_value();
- else
- throw ConfigurationError("Deserializing nil into a non-nullable object");
- } else if (item_str == "1") {
- new_value = true;
- } else if (item_str == "0") {
- new_value = false;
- } else if (substitution != ConfigHelpers::DeserializationSubstitution::Disabled && ConfigHelpers::looks_like_enum_value(item_str)) {
- new_value = ConfigHelpers::enum_looks_like_true_value(item_str) || substitution == ConfigHelpers::DeserializationSubstitution::DefaultsToTrue;
- substituted = true;
- } else
- return ConfigHelpers::DeserializationResult::Failed;
- this->values.push_back(new_value);
- }
- return substituted ? ConfigHelpers::DeserializationResult::Substituted : ConfigHelpers::DeserializationResult::Loaded;
- }
- bool deserialize(const std::string &str, bool append = false) override
- {
- return this->deserialize_with_substitutions(str, append, ConfigHelpers::DeserializationSubstitution::Disabled) == ConfigHelpers::DeserializationResult::Loaded;
- }
- protected:
- void serialize_single_value(std::ostringstream &ss, const unsigned char v) const {
- if (v == nil_value()) {
- if (NULLABLE)
- ss << "nil";
- else
- throw ConfigurationError("Serializing NaN");
- } else
- ss << (v ? "1" : "0");
- }
- private:
- friend class cereal::access;
- template<class Archive> void serialize(Archive &ar) { ar(cereal::base_class<ConfigOptionVector<unsigned char>>(this)); }
- };
- using ConfigOptionBools = ConfigOptionBoolsTempl<false>;
- using ConfigOptionBoolsNullable = ConfigOptionBoolsTempl<true>;
- // Map from an enum integer value to an enum name.
- typedef std::vector<std::string> t_config_enum_names;
- // Map from an enum name to an enum integer value.
- typedef std::map<std::string,int32_t> t_config_enum_values;
- 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 { return this->value == rhs.value; }
- int32_t getInt() const override { return (int32_t)this->value; }
- 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();
- this->flags = rhs->flags;
- }
- std::string serialize() const override
- {
- // as names are static-initialized, it's thread safe
- static t_config_enum_names names = ConfigOptionEnum<T>::create_enum_names();
- assert(static_cast<int32_t>(this->value) < int32_t(names.size()));
- return names[static_cast<int32_t>(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 std::pair<std::string, int32_t> &kvp : ConfigOptionEnum<T>::get_enum_values())
- if (kvp.second == value)
- return true;
- return false;
- }
- // Map from an enum name to an enum integer value. Can be used for static initialisation
- static t_config_enum_names create_enum_names()
- {
- t_config_enum_names names;
- if (names.empty()) {
- // Initialize the map.
- const t_config_enum_values &enum_keys_map = ConfigOptionEnum<T>::get_enum_values();
- int32_t cnt = 0;
- for (const std::pair<std::string, int32_t> &kvp : enum_keys_map)
- cnt = std::max(cnt, kvp.second);
- cnt += 1;
- names.assign(cnt, "");
- for (const std::pair<std::string, int32_t> &kvp : enum_keys_map)
- names[kvp.second] = kvp.first;
- }
- return 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;
- }
- };
- // Generic enum configuration value.
- // We use this one in DynamicConfig objects when creating a config value object for ConfigOptionType == coEnum.
- // In the StaticConfig, it is better to use the specialized ConfigOptionEnum<T> containers.
- class ConfigOptionEnumGeneric : public ConfigOptionInt
- {
- public:
- ConfigOptionEnumGeneric(const t_config_enum_values* keys_map = nullptr) : keys_map(keys_map) {}
- explicit ConfigOptionEnumGeneric(const t_config_enum_values* keys_map, int32_t value) : ConfigOptionInt(value), keys_map(keys_map) {}
- const t_config_enum_values* keys_map;
-
- static ConfigOptionType static_type() { return coEnum; }
- ConfigOptionType type() const override { return static_type(); }
- ConfigOption* clone() const override { return new ConfigOptionEnumGeneric(*this); }
- ConfigOptionEnumGeneric& operator=(const ConfigOption *opt) { this->set(opt); return *this; }
- bool operator==(const ConfigOptionEnumGeneric &rhs) const { return this->value == rhs.value; }
- bool operator==(const ConfigOption &rhs) const override
- {
- if (rhs.type() != this->type())
- throw ConfigurationError("ConfigOptionEnumGeneric: Comparing incompatible types");
- // rhs could be of the following type: ConfigOptionEnumGeneric or ConfigOptionEnum<T>
- return this->value == rhs.getInt();
- }
- void set(const ConfigOption *rhs) override {
- if (rhs->type() != this->type())
- throw ConfigurationError("ConfigOptionEnumGeneric: Assigning an incompatible type");
- // rhs could be of the following type: ConfigOptionEnumGeneric or ConfigOptionEnum<T>
- this->value = rhs->getInt();
- this->flags = rhs->flags;
- }
- std::string serialize() const override
- {
- for (const auto &kvp : *this->keys_map)
- if (kvp.second == this->value)
- return kvp.first;
- return std::string();
- }
- bool deserialize(const std::string &str, bool append = false) override
- {
- UNUSED(append);
- auto it = this->keys_map->find(str);
- if (it == this->keys_map->end())
- return false;
- this->value = it->second;
- return true;
- }
- private:
- friend class cereal::access;
- template<class Archive> void serialize(Archive& ar) { ar(cereal::base_class<ConfigOptionInt>(this)); }
- };
- // Definition of a configuration value for the purpose of GUI presentation, editing, value mapping and config file handling.
- class ConfigOptionDef
- {
- public:
- // Identifier of this option. It is stored here so that it is accessible through the by_serialization_key_ordinal map.
- t_config_option_key opt_key;
- // What type? bool, int, string etc.
- ConfigOptionType type = coNone;
- // If a type is nullable, then it accepts a "nil" value (scalar) or "nil" values (vector).
- bool nullable = false;
- // Default value of this option. The default value object is owned by ConfigDef, it is released in its destructor.
- Slic3r::clonable_ptr<const ConfigOption> default_value;
- void set_default_value(const ConfigOption* ptr) {
- this->default_value = Slic3r::clonable_ptr<const ConfigOption>(ptr);
- }
- void set_default_value(ConfigOptionVectorBase* ptr) {
- ptr->set_is_extruder_size(this->is_vector_extruder);
- this->default_value = Slic3r::clonable_ptr<const ConfigOption>(ptr);
- }
- template<typename T> const T* get_default_value() const { return static_cast<const T*>(this->default_value.get()); }
- // Create an empty option to be used as a base for deserialization of DynamicConfig.
- ConfigOption* create_empty_option() const;
- // Create a default option to be inserted into a DynamicConfig.
- ConfigOption* create_default_option() const;
- template<class Archive> ConfigOption* load_option_from_archive(Archive &archive) const {
- if (this->nullable) {
- switch (this->type) {
- case coFloats: { auto opt = new ConfigOptionFloatsNullable(); archive(*opt); opt->set_is_extruder_size(this->is_vector_extruder); return opt; }
- case coInts: { auto opt = new ConfigOptionIntsNullable(); archive(*opt); opt->set_is_extruder_size(this->is_vector_extruder); return opt; }
- case coPercents: { auto opt = new ConfigOptionPercentsNullable();archive(*opt); opt->set_is_extruder_size(this->is_vector_extruder); return opt; }
- case coFloatsOrPercents:{ auto opt = new ConfigOptionFloatsOrPercentsNullable();archive(*opt); opt->set_is_extruder_size(this->is_vector_extruder); return opt; }
- case coBools: { auto opt = new ConfigOptionBoolsNullable(); archive(*opt); opt->set_is_extruder_size(this->is_vector_extruder); return opt; }
- default: throw ConfigurationError(std::string("ConfigOptionDef::load_option_from_archive(): Unknown nullable option type for option ") + this->opt_key);
- }
- } else {
- switch (this->type) {
- case coFloat: { auto opt = new ConfigOptionFloat(); archive(*opt); return opt; }
- case coFloats: { auto opt = new ConfigOptionFloats(); archive(*opt); opt->set_is_extruder_size(this->is_vector_extruder); return opt; }
- case coInt: { auto opt = new ConfigOptionInt(); archive(*opt); return opt; }
- case coInts: { auto opt = new ConfigOptionInts(); archive(*opt); opt->set_is_extruder_size(this->is_vector_extruder); return opt; }
- case coString: { auto opt = new ConfigOptionString(); archive(*opt); return opt; }
- case coStrings: { auto opt = new ConfigOptionStrings(); archive(*opt); opt->set_is_extruder_size(this->is_vector_extruder); return opt; }
- case coPercent: { auto opt = new ConfigOptionPercent(); archive(*opt); return opt; }
- case coPercents: { auto opt = new ConfigOptionPercents(); archive(*opt); opt->set_is_extruder_size(this->is_vector_extruder); return opt; }
- case coFloatOrPercent: { auto opt = new ConfigOptionFloatOrPercent(); archive(*opt); return opt; }
- case coFloatsOrPercents:{ auto opt = new ConfigOptionFloatsOrPercents();archive(*opt); opt->set_is_extruder_size(this->is_vector_extruder); return opt; }
- case coPoint: { auto opt = new ConfigOptionPoint(); archive(*opt); return opt; }
- case coPoints: { auto opt = new ConfigOptionPoints(); archive(*opt); opt->set_is_extruder_size(this->is_vector_extruder); return opt; }
- case coPoint3: { auto opt = new ConfigOptionPoint3(); archive(*opt); return opt; }
- case coBool: { auto opt = new ConfigOptionBool(); archive(*opt); return opt; }
- case coBools: { auto opt = new ConfigOptionBools(); archive(*opt); opt->set_is_extruder_size(this->is_vector_extruder); return opt; }
- case coEnum: { auto opt = new ConfigOptionEnumGeneric(this->enum_keys_map); archive(*opt); return opt; }
- default: throw ConfigurationError(std::string("ConfigOptionDef::load_option_from_archive(): Unknown option type for option ") + this->opt_key);
- }
- }
- }
- template<class Archive> ConfigOption* save_option_to_archive(Archive &archive, const ConfigOption *opt) const {
- if (this->nullable) {
- switch (this->type) {
- case coFloats: archive(*static_cast<const ConfigOptionFloatsNullable*>(opt)); break;
- case coInts: archive(*static_cast<const ConfigOptionIntsNullable*>(opt)); break;
- case coPercents: archive(*static_cast<const ConfigOptionPercentsNullable*>(opt));break;
- case coFloatsOrPercents:archive(*static_cast<const ConfigOptionFloatsOrPercentsNullable*>(opt));break;
- case coBools: archive(*static_cast<const ConfigOptionBoolsNullable*>(opt)); break;
- default: throw ConfigurationError(std::string("ConfigOptionDef::save_option_to_archive(): Unknown nullable option type for option ") + this->opt_key);
- }
- } else {
- switch (this->type) {
- case coFloat: archive(*static_cast<const ConfigOptionFloat*>(opt)); break;
- case coFloats: archive(*static_cast<const ConfigOptionFloats*>(opt)); break;
- case coInt: archive(*static_cast<const ConfigOptionInt*>(opt)); break;
- case coInts: archive(*static_cast<const ConfigOptionInts*>(opt)); break;
- case coString: archive(*static_cast<const ConfigOptionString*>(opt)); break;
- case coStrings: archive(*static_cast<const ConfigOptionStrings*>(opt)); break;
- case coPercent: archive(*static_cast<const ConfigOptionPercent*>(opt)); break;
- case coPercents: archive(*static_cast<const ConfigOptionPercents*>(opt)); break;
- case coFloatOrPercent: archive(*static_cast<const ConfigOptionFloatOrPercent*>(opt)); break;
- case coFloatsOrPercents:archive(*static_cast<const ConfigOptionFloatsOrPercents*>(opt));break;
- case coPoint: archive(*static_cast<const ConfigOptionPoint*>(opt)); break;
- case coPoints: archive(*static_cast<const ConfigOptionPoints*>(opt)); break;
- case coPoint3: archive(*static_cast<const ConfigOptionPoint3*>(opt)); break;
- case coBool: archive(*static_cast<const ConfigOptionBool*>(opt)); break;
- case coBools: archive(*static_cast<const ConfigOptionBools*>(opt)); break;
- case coEnum: archive(*static_cast<const ConfigOptionEnumGeneric*>(opt)); break;
- default: throw ConfigurationError(std::string("ConfigOptionDef::save_option_to_archive(): Unknown option type for option ") + this->opt_key);
- }
- }
- // Make the compiler happy, shut up the warnings.
- return nullptr;
- }
- // Usually empty.
- // Special values - "i_enum_open", "f_enum_open" to provide combo box for int or float selection,
- // "select_open" - to open a selection dialog (currently only a serial port selection).
- std::string gui_type;
- // Usually empty. Otherwise "serialized" or "show_value"
- // The flags may be combined.
- // "serialized" - vector valued option is entered in a single edit field. Values are separated by a semicolon.
- // "show_value" - even if enum_values / enum_labels are set, still display the value, not the enum label.
- std::string gui_flags;
- // Label of the GUI input field.
- // In case the GUI input fields are grouped in some views, the label defines a short label of a grouped value,
- // while full_label contains a label of a stand-alone field.
- // The full label is shown, when adding an override parameter for an object or a modified object.
- std::string label;
- std::string full_label;
- std::string get_full_label() const { return !full_label.empty() ? full_label : label; }
- // With which printer technology is this configuration valid?
- PrinterTechnology printer_technology = ptUnknown;
- // Category of a configuration field, from the GUI perspective.
- OptionCategory category = OptionCategory::none;
- // A tooltip text shown in the GUI.
- std::string tooltip;
- // Text right from the input field, usually a unit of measurement.
- std::string sidetext;
- // Format of this parameter on a command line.
- std::string cli;
- // Set for type == coFloatOrPercent.
- // It provides a link to a configuration value, of which this option provides a ratio.
- // For example,
- // For example external_perimeter_speed may be defined as a fraction of perimeter_speed.
- t_config_option_key ratio_over;
- // True for multiline strings.
- bool multiline = false;
- // For text input: If true, the GUI text box spans the complete page width.
- bool full_width = false;
- // For text input: If true, the GUI formats text as code (fixed-width)
- bool is_code = false;
- // For array setting: If true, It has the same size as the number of extruders.
- bool is_vector_extruder = false;
- // Not editable. Currently only used for the display of the number of threads.
- bool readonly = false;
- // Can be phony. if not present at laoding, mark it as phony. Also adapt the gui to look for phony status.
- bool can_phony = false;
- // Height of a multiline GUI text box.
- int height = -1;
- // Optional width of an input field.
- int width = -1;
- // Optional label width of the label (if in a line).
- int label_width = -1;
- // Optional label alignement to the left instead of the right
- bool aligned_label_left = false;
- // Optional label width of the sidetext (if in a line).
- int sidetext_width = -1;
- // <min, max> limit of a numeric input.
- // If not set, the <min, max> is set to <INT_MIN, INT_MAX>
- // By setting min=0, only nonnegative input is allowed.
- double min = INT_MIN;
- double max = INT_MAX;
- // To check if it's not a typo and a % is missing
- FloatOrPercent max_literal = FloatOrPercent{ 0., false };
- // max precision after the dot, only for display
- int precision = 6;
- ConfigOptionMode mode = comSimple;
- // Legacy names for this configuration option.
- // Used when parsing legacy configuration file.
- std::vector<t_config_option_key> aliases;
- // Sometimes a single value may well define multiple values in a "beginner" mode.
- // Currently used for aliasing "solid_layers" to "top_solid_layers", "bottom_solid_layers".
- std::vector<t_config_option_key> shortcut;
- // Definition of values / labels for a combo box.
- // Mostly used for enums (when type == coEnum), but may be used for ints resp. floats, if gui_type is set to "i_enum_open" resp. "f_enum_open".
- std::vector<std::string> enum_values;
- std::vector<std::string> enum_labels;
- // For enums (when type == coEnum). Maps enum_values to enums.
- // Initialized by ConfigOptionEnum<xxx>::get_enum_values()
- const t_config_enum_values *enum_keys_map = nullptr;
- bool has_enum_value(const std::string &value) const {
- for (const std::string &v : enum_values)
- if (v == value)
- return true;
- return false;
- }
- // 0 is an invalid key.
- size_t serialization_key_ordinal = 0;
- // Returns the alternative CLI arguments for the given option.
- // If there are no cli arguments defined, use the key and replace underscores with dashes.
- std::vector<std::string> cli_args(const std::string &key) const;
- // Assign this key to cli to disable CLI for this option.
- static const constexpr char *nocli = "~~~noCLI";
- };
- inline bool operator<(const ConfigSubstitution &lhs, const ConfigSubstitution &rhs) throw() {
- return lhs.opt_def->opt_key < rhs.opt_def->opt_key ||
- (lhs.opt_def->opt_key == rhs.opt_def->opt_key && lhs.old_value < rhs.old_value);
- }
- inline bool operator==(const ConfigSubstitution &lhs, const ConfigSubstitution &rhs) throw() {
- return lhs.opt_def == rhs.opt_def && lhs.old_value == rhs.old_value;
- }
- // Map from a config option name to its definition.
- // The definition does not carry an actual value of the config option, only its constant default value.
- // t_config_option_key is std::string
- typedef std::map<t_config_option_key, ConfigOptionDef> t_optiondef_map;
- // Definition of configuration values for the purpose of GUI presentation, editing, value mapping and config file handling.
- // The configuration definition is static: It does not carry the actual configuration values,
- // but it carries the defaults of the configuration values.
- class ConfigDef
- {
- public:
- t_optiondef_map options;
- std::map<size_t, const ConfigOptionDef*> by_serialization_key_ordinal;
- bool has(const t_config_option_key &opt_key) const { return this->options.count(opt_key) > 0; }
- const ConfigOptionDef* get(const t_config_option_key &opt_key) const {
- t_optiondef_map::iterator it = const_cast<ConfigDef*>(this)->options.find(opt_key);
- return (it == this->options.end()) ? nullptr : &it->second;
- }
- std::vector<std::string> keys() const {
- std::vector<std::string> out;
- out.reserve(options.size());
- for(auto const& kvp : options)
- out.push_back(kvp.first);
- return out;
- }
- // Iterate through all of the CLI options and write them to a stream.
- std::ostream& print_cli_help(
- std::ostream& out, bool show_defaults,
- std::function<bool(const ConfigOptionDef &)> filter = [](const ConfigOptionDef &){ return true; }) const;
- protected:
- ConfigOptionDef* add(const t_config_option_key &opt_key, ConfigOptionType type);
- ConfigOptionDef* add_nullable(const t_config_option_key &opt_key, ConfigOptionType type);
- };
- // A pure interface to resolving ConfigOptions.
- // This pure interface is useful as a base of ConfigBase, also it may be overriden to combine
- // various config sources.
- class ConfigOptionResolver
- {
- public:
- ConfigOptionResolver() {}
- virtual ~ConfigOptionResolver() {}
- // Find a ConfigOption instance for a given name.
- virtual const ConfigOption* optptr(const t_config_option_key &opt_key) const = 0;
- bool has(const t_config_option_key &opt_key) const { return this->optptr(opt_key) != nullptr; }
-
- const ConfigOption* option(const t_config_option_key &opt_key) const { return this->optptr(opt_key); }
- template<typename TYPE>
- const TYPE* option(const t_config_option_key& opt_key) const
- {
- const ConfigOption* opt = this->optptr(opt_key);
- return (opt == nullptr || opt->type() != TYPE::static_type()) ? nullptr : static_cast<const TYPE*>(opt);
- }
- const ConfigOption* option_throw(const t_config_option_key& opt_key) const
- {
- const ConfigOption* opt = this->optptr(opt_key);
- if (opt == nullptr)
- throw UnknownOptionException(opt_key);
- return opt;
- }
- template<typename TYPE>
- const TYPE* option_throw(const t_config_option_key& opt_key) const
- {
- const ConfigOption* opt = this->option_throw(opt_key);
- if (opt->type() != TYPE::static_type())
- throw BadOptionTypeException("Conversion to a wrong type");
- return static_cast<TYPE*>(opt);
- }
- };
- // An abstract configuration store.
- class ConfigBase : public ConfigOptionResolver
- {
- public:
- // Definition of configuration values for the purpose of GUI presentation, editing, value mapping and config file handling.
- // The configuration definition is static: It does not carry the actual configuration values,
- // but it carries the defaults of the configuration values.
-
- ConfigBase() {}
- ~ConfigBase() override {}
- // to get to the config more generic than this one, if available
- const ConfigBase* parent = nullptr;
- // Virtual overridables:
- public:
- // Static configuration definition. Any value stored into this ConfigBase shall have its definition here.
- // will search in parent definition if not found here.
- virtual const ConfigDef* def() const = 0;
- // Find ando/or create a ConfigOption instance for a given name.
- // won't search in parent definition, as you can't change a parent value
- virtual ConfigOption* optptr(const t_config_option_key &opt_key, bool create = false) = 0;
- // Collect names of all configuration values maintained by this configuration store.
- virtual t_config_option_keys keys() const = 0;
- protected:
- // Verify whether the opt_key has not been obsoleted or renamed.
- // Both opt_key and value may be modified by handle_legacy().
- // If the opt_key is no more valid in this version of Slic3r, opt_key is cleared by handle_legacy().
- // handle_legacy() is called internally by set_deserialize().
- virtual void handle_legacy(t_config_option_key&/*opt_key*/, std::string&/*value*/) const {}
- // Verify whether the opt_key has to be converted or isn't present int prusaslicer
- // Both opt_key and value may be modified by to_prusa().
- // If the opt_key is no more valid in this version of Slic3r, opt_key is cleared by to_prusa().
- virtual void to_prusa(t_config_option_key&/*opt_key*/, std::string&/*value*/) const {}
- public:
- using ConfigOptionResolver::option;
- using ConfigOptionResolver::option_throw;
- // Non-virtual methods:
- ConfigOption* option(const t_config_option_key &opt_key, bool create = false)
- { return this->optptr(opt_key, create); }
-
- template<typename TYPE>
- TYPE* option(const t_config_option_key &opt_key, bool create = false)
- {
- ConfigOption *opt = this->optptr(opt_key, create);
- return (opt == nullptr || opt->type() != TYPE::static_type()) ? nullptr : static_cast<TYPE*>(opt);
- }
- ConfigOption* option_throw(const t_config_option_key &opt_key, bool create = false)
- {
- ConfigOption *opt = this->optptr(opt_key, create);
- if (opt == nullptr)
- throw UnknownOptionException(opt_key);
- return opt;
- }
-
- template<typename TYPE>
- TYPE* option_throw(const t_config_option_key &opt_key, bool create = false)
- {
- ConfigOption *opt = this->option_throw(opt_key, create);
- if (opt->type() != TYPE::static_type())
- throw BadOptionTypeException("Conversion to a wrong type");
- return static_cast<TYPE*>(opt);
- }
-
- // Apply all keys of other ConfigBase defined by this->def() to this ConfigBase.
- // An UnknownOptionException is thrown in case some option keys of other are not defined by this->def(),
- // or this ConfigBase is of a StaticConfig type and it does not support some of the keys, and ignore_nonexistent is not set.
- void apply(const ConfigBase &other, bool ignore_nonexistent = false) { this->apply_only(other, other.keys(), ignore_nonexistent); }
- // Apply explicitely enumerated keys of other ConfigBase defined by this->def() to this ConfigBase.
- // An UnknownOptionException is thrown in case some option keys are not defined by this->def(),
- // or this ConfigBase is of a StaticConfig type and it does not support some of the keys, and ignore_nonexistent is not set.
- void apply_only(const ConfigBase &other, const t_config_option_keys &keys, bool ignore_nonexistent = false);
- bool equals(const ConfigBase &other) const { return this->keys().size() == other.keys().size() && this->diff(other).empty(); }
- t_config_option_keys diff(const ConfigBase &other, bool even_phony = true) const;
- t_config_option_keys equal(const ConfigBase &other) const;
- std::string opt_serialize(const t_config_option_key &opt_key) const;
- // Set a value. Convert numeric types using a C style implicit conversion / promotion model.
- // Throw if option is not avaiable and create is not enabled,
- // or if the conversion is not possible.
- // Conversion to string is always possible.
- void set(const std::string &opt_key, bool value, bool create = false)
- { this->option_throw<ConfigOptionBool>(opt_key, create)->value = value; }
- void set(const std::string &opt_key, int32_t value, bool create = false);
- void set(const std::string &opt_key, double value, bool create = false);
- void set(const std::string &opt_key, const char *value, bool create = false)
- { this->option_throw<ConfigOptionString>(opt_key, create)->value = value; }
- void set(const std::string &opt_key, const std::string &value, bool create = false)
- { this->option_throw<ConfigOptionString>(opt_key, create)->value = value; }
- // Set a configuration value from a string, it will call an overridable handle_legacy()
- // to resolve renamed and removed configuration keys.
- bool set_deserialize_nothrow(const t_config_option_key &opt_key_src, const std::string &value_src, ConfigSubstitutionContext& substitutions, bool append = false);
- // May throw BadOptionTypeException() if the operation fails.
- void set_deserialize(const t_config_option_key &opt_key, const std::string &str, ConfigSubstitutionContext& config_substitutions, bool append = false);
- void set_deserialize_strict(const t_config_option_key &opt_key, const std::string &str, bool append = false)
- { ConfigSubstitutionContext ctxt{ ForwardCompatibilitySubstitutionRule::Disable }; this->set_deserialize(opt_key, str, ctxt, append); }
- struct SetDeserializeItem {
- SetDeserializeItem(const char *opt_key, const char *opt_value, bool append = false) : opt_key(opt_key), opt_value(opt_value), append(append) {}
- SetDeserializeItem(const std::string &opt_key, const std::string &opt_value, bool append = false) : opt_key(opt_key), opt_value(opt_value), append(append) {}
- SetDeserializeItem(const char *opt_key, const bool value, bool append = false) : opt_key(opt_key), opt_value(value ? "1" : "0"), append(append) {}
- SetDeserializeItem(const std::string &opt_key, const bool value, bool append = false) : opt_key(opt_key), opt_value(value ? "1" : "0"), append(append) {}
- SetDeserializeItem(const char *opt_key, const int32_t value, bool append = false) : opt_key(opt_key), opt_value(std::to_string(value)), append(append) {}
- SetDeserializeItem(const std::string &opt_key, const int32_t value, bool append = false) : opt_key(opt_key), opt_value(std::to_string(value)), append(append) {}
- SetDeserializeItem(const char *opt_key, const float value, bool append = false) : opt_key(opt_key), opt_value(std::to_string(value)), append(append) {}
- SetDeserializeItem(const std::string &opt_key, const float value, bool append = false) : opt_key(opt_key), opt_value(std::to_string(value)), append(append) {}
- SetDeserializeItem(const char *opt_key, const double value, bool append = false) : opt_key(opt_key), opt_value(std::to_string(value)), append(append) {}
- SetDeserializeItem(const std::string &opt_key, const double value, bool append = false) : opt_key(opt_key), opt_value(std::to_string(value)), append(append) {}
- std::string opt_key; std::string opt_value; bool append = false;
- };
- // May throw BadOptionTypeException() if the operation fails.
- void set_deserialize(std::initializer_list<SetDeserializeItem> items, ConfigSubstitutionContext& substitutions);
- void set_deserialize_strict(std::initializer_list<SetDeserializeItem> items)
- { ConfigSubstitutionContext ctxt{ ForwardCompatibilitySubstitutionRule::Disable }; this->set_deserialize(items, ctxt); }
- const ConfigOptionDef* get_option_def(const t_config_option_key& opt_key) const;
- double get_computed_value(const t_config_option_key &opt_key, int extruder_id = -1) const;
- double get_abs_value(const t_config_option_key &opt_key, double ratio_over) const;
- void setenv_() const;
- ConfigSubstitutions load(const std::string &file, ForwardCompatibilitySubstitutionRule compatibility_rule);
- ConfigSubstitutions load_from_ini(const std::string &file, ForwardCompatibilitySubstitutionRule compatibility_rule);
- ConfigSubstitutions load_from_gcode_file(const std::string &file, ForwardCompatibilitySubstitutionRule compatibility_rule);
- // Returns number of key/value pairs extracted.
- size_t load_from_gcode_string(const char* str, ConfigSubstitutionContext& substitutions);
- ConfigSubstitutions load(const boost::property_tree::ptree &tree, ForwardCompatibilitySubstitutionRule compatibility_rule);
- void save(const std::string &file, bool to_prusa = false) const;
- // Set all the nullable values to nils.
- void null_nullables();
- private:
- // Set a configuration value from a string.
- bool set_deserialize_raw(const t_config_option_key& opt_key_src, const std::string& value, ConfigSubstitutionContext& substitutions, bool append);
- };
- // Configuration store with dynamic number of configuration values.
- // In Slic3r, the dynamic config is mostly used at the user interface layer.
- class DynamicConfig : public virtual ConfigBase
- {
- public:
- DynamicConfig() {}
- DynamicConfig(const DynamicConfig &rhs) { *this = rhs; }
- DynamicConfig(DynamicConfig &&rhs) noexcept : options(std::move(rhs.options)) { rhs.options.clear(); }
- explicit DynamicConfig(const ConfigBase &rhs, const t_config_option_keys &keys);
- explicit DynamicConfig(const ConfigBase& rhs) : DynamicConfig(rhs, rhs.keys()) {}
- virtual ~DynamicConfig() override { clear(); }
- // Copy a content of one DynamicConfig to another DynamicConfig.
- // If rhs.def() is not null, then it has to be equal to this->def().
- DynamicConfig& operator=(const DynamicConfig &rhs)
- {
- assert(this->def() == nullptr || this->def() == rhs.def());
- this->clear();
- for (const auto &kvp : rhs.options)
- this->options[kvp.first].reset(kvp.second->clone());
- return *this;
- }
- // Move a content of one DynamicConfig to another DynamicConfig.
- // If rhs.def() is not null, then it has to be equal to this->def().
- DynamicConfig& operator=(DynamicConfig &&rhs) noexcept
- {
- assert(this->def() == nullptr || this->def() == rhs.def());
- this->clear();
- this->options = std::move(rhs.options);
- rhs.options.clear();
- return *this;
- }
- // Add a content of one DynamicConfig to another DynamicConfig.
- // If rhs.def() is not null, then it has to be equal to this->def().
- DynamicConfig& operator+=(const DynamicConfig &rhs)
- {
- assert(this->def() == nullptr || this->def() == rhs.def());
- for (const auto &kvp : rhs.options) {
- auto it = this->options.find(kvp.first);
- if (it == this->options.end())
- this->options[kvp.first].reset(kvp.second->clone());
- else {
- assert(it->second->type() == kvp.second->type());
- if (it->second->type() == kvp.second->type())
- *it->second = *kvp.second;
- else
- it->second.reset(kvp.second->clone());
- }
- }
- return *this;
- }
- // Move a content of one DynamicConfig to another DynamicConfig.
- // If rhs.def() is not null, then it has to be equal to this->def().
- DynamicConfig& operator+=(DynamicConfig &&rhs)
- {
- assert(this->def() == nullptr || this->def() == rhs.def());
- for (auto &kvp : rhs.options) {
- auto it = this->options.find(kvp.first);
- if (it == this->options.end()) {
- this->options.insert(std::make_pair(kvp.first, std::move(kvp.second)));
- } else {
- assert(it->second->type() == kvp.second->type());
- it->second = std::move(kvp.second);
- }
- }
- rhs.options.clear();
- return *this;
- }
- bool operator==(const DynamicConfig &rhs) const;
- bool operator!=(const DynamicConfig &rhs) const { return ! (*this == rhs); }
- void swap(DynamicConfig &other)
- {
- std::swap(this->options, other.options);
- }
- void clear()
- {
- this->options.clear();
- }
- bool erase(const t_config_option_key &opt_key)
- {
- auto it = this->options.find(opt_key);
- if (it == this->options.end())
- return false;
- this->options.erase(it);
- return true;
- }
- // Remove options with all nil values, those are optional and it does not help to hold them.
- size_t remove_nil_options();
- // Allow DynamicConfig to be instantiated on ints own without a definition.
- // If the definition is not defined, the method requiring the definition will throw NoDefinitionException.
- const ConfigDef* def() const override { return nullptr; }
- template<class T> T* opt(const t_config_option_key &opt_key, bool create = false)
- { return dynamic_cast<T*>(this->option(opt_key, create)); }
- template<class T> const T* opt(const t_config_option_key &opt_key) const
- { return dynamic_cast<const T*>(this->option(opt_key)); }
- // Overrides ConfigResolver::optptr().
- const ConfigOption* optptr(const t_config_option_key &opt_key) const override;
- // Overrides ConfigBase::optptr(). Find ando/or create a ConfigOption instance for a given name.
- ConfigOption* optptr(const t_config_option_key &opt_key, bool create = false) override;
- // Overrides ConfigBase::keys(). Collect names of all configuration values maintained by this configuration store.
- t_config_option_keys keys() const override;
- bool empty() const { return options.empty(); }
- // Set a value for an opt_key. Returns true if the value did not exist yet.
- // This DynamicConfig will take ownership of opt.
- // Be careful, as this method does not test the existence of opt_key in this->def().
- bool set_key_value(const std::string &opt_key, ConfigOption *opt)
- {
- auto it = this->options.find(opt_key);
- if (it == this->options.end()) {
- this->options[opt_key].reset(opt);
- return true;
- } else {
- it->second.reset(opt);
- return false;
- }
- }
- std::string& opt_string(const t_config_option_key &opt_key, bool create = false) { return this->option<ConfigOptionString>(opt_key, create)->value; }
- const std::string& opt_string(const t_config_option_key &opt_key) const { return const_cast<DynamicConfig*>(this)->opt_string(opt_key); }
- std::string& opt_string(const t_config_option_key &opt_key, unsigned int idx) { return this->option<ConfigOptionStrings>(opt_key)->get_at(idx); }
- const std::string& opt_string(const t_config_option_key &opt_key, unsigned int idx) const { return const_cast<DynamicConfig*>(this)->opt_string(opt_key, idx); }
- double& opt_float(const t_config_option_key &opt_key) { return this->option<ConfigOptionFloat>(opt_key)->value; }
- const double& opt_float(const t_config_option_key &opt_key) const { return dynamic_cast<const ConfigOptionFloat*>(this->option(opt_key))->value; }
- double& opt_float(const t_config_option_key &opt_key, unsigned int idx) { return this->option<ConfigOptionFloats>(opt_key)->get_at(idx); }
- const double& opt_float(const t_config_option_key &opt_key, unsigned int idx) const { return dynamic_cast<const ConfigOptionFloats*>(this->option(opt_key))->get_at(idx); }
- int32_t& opt_int(const t_config_option_key &opt_key) { return this->option<ConfigOptionInt>(opt_key)->value; }
- int32_t opt_int(const t_config_option_key &opt_key) const { return dynamic_cast<const ConfigOptionInt*>(this->option(opt_key))->value; }
- int32_t& opt_int(const t_config_option_key &opt_key, unsigned int idx) { return this->option<ConfigOptionInts>(opt_key)->get_at(idx); }
- int32_t opt_int(const t_config_option_key &opt_key, unsigned int idx) const { return dynamic_cast<const ConfigOptionInts*>(this->option(opt_key))->get_at(idx); }
- template<typename ENUM>
- ENUM opt_enum(const t_config_option_key &opt_key) const {
- auto v1 = this->option<ConfigOptionEnumGeneric>(opt_key);
- auto v2 = this->option<ConfigOptionEnum<ENUM>>(opt_key);
- return v1==nullptr? v2->value : (ENUM)v1->value;
- }
- bool opt_bool(const t_config_option_key &opt_key) const { return this->option<ConfigOptionBool>(opt_key)->value != 0; }
- bool opt_bool(const t_config_option_key &opt_key, unsigned int idx) const { return this->option<ConfigOptionBools>(opt_key)->get_at(idx) != 0; }
- // Command line processing
- void read_cli(const std::vector<std::string> &tokens, t_config_option_keys* extra, t_config_option_keys* keys = nullptr);
- bool read_cli(int argc, const char* const argv[], t_config_option_keys* extra, t_config_option_keys* keys = nullptr);
- std::map<t_config_option_key, std::unique_ptr<ConfigOption>>::const_iterator cbegin() const { return options.cbegin(); }
- std::map<t_config_option_key, std::unique_ptr<ConfigOption>>::const_iterator cend() const { return options.cend(); }
- size_t size() const { return options.size(); }
- private:
- std::map<t_config_option_key, std::unique_ptr<ConfigOption>> options;
- friend class cereal::access;
- template<class Archive> void serialize(Archive &ar) { ar(options); }
- };
- // Configuration store with a static definition of configuration values.
- // In Slic3r, the static configuration stores are during the slicing / g-code generation for efficiency reasons,
- // because the configuration values could be accessed directly.
- class StaticConfig : public virtual ConfigBase
- {
- public:
- /// Gets list of config option names for each config option of this->def, which has a static counter-part defined by the derived object
- /// and which could be resolved by this->optptr(key) call.
- t_config_option_keys keys() const;
- /// Set all statically defined config options to their defaults defined by this->def().
- /// used (only) by tests
- void set_defaults();
- protected:
- StaticConfig() {}
- };
- }
- #endif
|