Port --load and --save to XS

This commit is contained in:
Alessandro Ranellucci 2016-07-17 16:53:37 +02:00
parent c2b06b22aa
commit 30139fd647
7 changed files with 107 additions and 41 deletions

View File

@ -87,8 +87,10 @@ sub load {
my $class = shift;
my ($file) = @_;
my $ini = __PACKAGE__->read_ini($file);
return $class->load_ini_hash($ini->{_});
# legacy syntax of load()
my $config = $class->new;
$config->_load($file);
return $config;
}
sub load_ini_hash {
@ -186,13 +188,6 @@ sub as_ini {
return $ini;
}
sub save {
my $self = shift;
my ($file) = @_;
__PACKAGE__->write_ini($file, $self->as_ini);
}
# this method is idempotent by design and only applies to ::DynamicConfig or ::Full
# objects because it performs cross checks
sub validate {

View File

@ -24,17 +24,28 @@ main(const int argc, const char **argv)
t_config_option_keys input_files;
config.read_cli(argc, argv, &input_files);
// apply command line options to a more specific DynamicPrintConfig which provides normalize()
DynamicPrintConfig print_config;
print_config.apply(config, true);
print_config.normalize();
// apply command line options to a more handy CLIConfig
CLIConfig cli_config;
cli_config.apply(config, true);
/* TODO: loop through the config files supplied on the command line (now stored in
cli_config), load each one, normalize it and apply it to print_config */
DynamicPrintConfig print_config;
// load config files supplied via --load
for (std::vector<std::string>::const_iterator file = cli_config.load.values.begin();
file != cli_config.load.values.end(); ++file) {
DynamicPrintConfig c;
c.load(*file);
c.normalize();
print_config.apply(c);
}
// apply command line options to a more specific DynamicPrintConfig which provides normalize()
// (command line options override --load files)
print_config.apply(config, true);
print_config.normalize();
// write config if requested
if (!cli_config.save.value.empty()) print_config.save(cli_config.save.value);
// read input file(s) if any
std::vector<Model> models;

View File

@ -1,8 +1,14 @@
#include "Config.hpp"
#include <stdlib.h> // for setenv()
#include <assert.h>
#include <ctime>
#include <fstream>
#include <iostream>
#include <boost/algorithm/string/erase.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/foreach.hpp>
#include <boost/property_tree/ini_parser.hpp>
#include <boost/property_tree/ptree.hpp>
#if defined(_WIN32) && !defined(setenv) && defined(_putenv_s)
#define setenv(k, v, o) _putenv_s(k, v)
@ -116,7 +122,7 @@ ConfigBase::serialize(const t_config_option_key &opt_key) const {
}
bool
ConfigBase::set_deserialize(const t_config_option_key &opt_key, std::string str) {
ConfigBase::set_deserialize(const t_config_option_key &opt_key, std::string str, bool append) {
const ConfigOptionDef* optdef = this->def->get(opt_key);
if (optdef == NULL) throw "Calling set_deserialize() on unknown option";
if (!optdef->shortcut.empty()) {
@ -128,7 +134,7 @@ ConfigBase::set_deserialize(const t_config_option_key &opt_key, std::string str)
ConfigOption* opt = this->option(opt_key, true);
assert(opt != NULL);
return opt->deserialize(str);
return opt->deserialize(str, append);
}
double
@ -189,6 +195,38 @@ ConfigBase::option(const t_config_option_key &opt_key, bool create) {
return this->optptr(opt_key, create);
}
void
ConfigBase::load(const std::string &file)
{
namespace pt = boost::property_tree;
pt::ptree tree;
pt::read_ini(file, tree);
BOOST_FOREACH(const pt::ptree::value_type &v, tree) {
this->set_deserialize(v.first.c_str(), v.second.get_value<std::string>().c_str());
}
}
void
ConfigBase::save(const std::string &file) const
{
using namespace std;
ofstream c;
c.open(file.c_str(), ios::out | ios::trunc);
{
time_t now;
time(&now);
char buf[sizeof "0000-00-00 00:00:00"];
strftime(buf, sizeof buf, "%F %T", gmtime(&now));
c << "# generated by Slic3r " << SLIC3R_VERSION << " on " << buf << endl;
}
t_config_option_keys my_keys = this->keys();
for (t_config_option_keys::const_iterator opt_key = my_keys.begin(); opt_key != my_keys.end(); ++opt_key)
c << *opt_key << " = " << this->serialize(*opt_key) << endl;
c.close();
}
DynamicConfig& DynamicConfig::operator= (DynamicConfig other)
{
this->swap(other);
@ -325,11 +363,11 @@ DynamicConfig::read_cli(const int argc, const char** argv, t_config_option_keys*
opt->values.push_back(!boost::starts_with(token, "no-"));
} else {
// we expect one more token carrying the value
if (i == argc) {
if (i == (argc-1)) {
printf("No value supplied for --%s\n", token.c_str());
exit(1);
}
this->option(opt_key, true)->deserialize(argv[++i]);
this->set_deserialize(opt_key, argv[++i], true);
}
} else {
extra->push_back(token);

View File

@ -22,7 +22,7 @@ class ConfigOption {
virtual ~ConfigOption() {};
virtual ConfigOption* clone() const = 0;
virtual std::string serialize() const = 0;
virtual bool deserialize(std::string str) = 0;
virtual bool deserialize(std::string str, bool append = false) = 0;
virtual void set(const ConfigOption &option) = 0;
virtual int getInt() const { return 0; };
virtual double getFloat() const { return 0; };
@ -90,7 +90,7 @@ class ConfigOptionFloat : public ConfigOptionSingle<double>
return ss.str();
};
bool deserialize(std::string str) {
bool deserialize(std::string str, bool append = false) {
std::istringstream iss(str);
iss >> this->value;
return !iss.fail();
@ -123,8 +123,8 @@ class ConfigOptionFloats : public ConfigOptionVector<double>
return vv;
};
bool deserialize(std::string str) {
this->values.clear();
bool deserialize(std::string str, bool append = false) {
if (!append) this->values.clear();
std::istringstream is(str);
std::string item_str;
while (std::getline(is, item_str, ',')) {
@ -153,7 +153,7 @@ class ConfigOptionInt : public ConfigOptionSingle<int>
return ss.str();
};
bool deserialize(std::string str) {
bool deserialize(std::string str, bool append = false) {
std::istringstream iss(str);
iss >> this->value;
return !iss.fail();
@ -186,8 +186,8 @@ class ConfigOptionInts : public ConfigOptionVector<int>
return vv;
};
bool deserialize(std::string str) {
this->values.clear();
bool deserialize(std::string str, bool append = false) {
if (!append) this->values.clear();
std::istringstream is(str);
std::string item_str;
while (std::getline(is, item_str, ',')) {
@ -222,7 +222,7 @@ class ConfigOptionString : public ConfigOptionSingle<std::string>
return str;
};
bool deserialize(std::string str) {
bool deserialize(std::string str, bool append = false) {
// s/\\n/\n/g
size_t pos = 0;
while ((pos = str.find("\\n", pos)) != std::string::npos) {
@ -256,8 +256,8 @@ class ConfigOptionStrings : public ConfigOptionVector<std::string>
return this->values;
};
bool deserialize(std::string str) {
this->values.clear();
bool deserialize(std::string str, bool append = false) {
if (!append) this->values.clear();
std::istringstream is(str);
std::string item_str;
while (std::getline(is, item_str, ';')) {
@ -286,7 +286,7 @@ class ConfigOptionPercent : public ConfigOptionFloat
return s;
};
bool deserialize(std::string str) {
bool deserialize(std::string str, bool append = false) {
// don't try to parse the trailing % since it's optional
std::istringstream iss(str);
iss >> this->value;
@ -327,7 +327,7 @@ class ConfigOptionFloatOrPercent : public ConfigOptionPercent
return s;
};
bool deserialize(std::string str) {
bool deserialize(std::string str, bool append = false) {
this->percent = str.find_first_of("%") != std::string::npos;
std::istringstream iss(str);
iss >> this->value;
@ -350,7 +350,7 @@ class ConfigOptionPoint : public ConfigOptionSingle<Pointf>
return ss.str();
};
bool deserialize(std::string str) {
bool deserialize(std::string str, bool append = false) {
std::istringstream iss(str);
iss >> this->value.x;
iss.ignore(std::numeric_limits<std::streamsize>::max(), ',');
@ -388,8 +388,8 @@ class ConfigOptionPoints : public ConfigOptionVector<Pointf>
return vv;
};
bool deserialize(std::string str) {
this->values.clear();
bool deserialize(std::string str, bool append = false) {
if (!append) this->values.clear();
std::istringstream is(str);
std::string point_str;
while (std::getline(is, point_str, ',')) {
@ -421,7 +421,7 @@ class ConfigOptionBool : public ConfigOptionSingle<bool>
return std::string(this->value ? "1" : "0");
};
bool deserialize(std::string str) {
bool deserialize(std::string str, bool append = false) {
this->value = (str.compare("1") == 0);
return true;
};
@ -453,8 +453,8 @@ class ConfigOptionBools : public ConfigOptionVector<bool>
return vv;
};
bool deserialize(std::string str) {
this->values.clear();
bool deserialize(std::string str, bool append = false) {
if (!append) this->values.clear();
std::istringstream is(str);
std::string item_str;
while (std::getline(is, item_str, ',')) {
@ -483,7 +483,7 @@ class ConfigOptionEnum : public ConfigOptionSingle<T>
return "";
};
bool deserialize(std::string str) {
bool deserialize(std::string str, bool append = false) {
t_config_enum_values enum_keys_map = ConfigOptionEnum<T>::get_enum_values();
if (enum_keys_map.count(str) == 0) return false;
this->value = static_cast<T>(enum_keys_map[str]);
@ -507,7 +507,7 @@ class ConfigOptionEnumGeneric : public ConfigOptionInt
return "";
};
bool deserialize(std::string str) {
bool deserialize(std::string str, bool append = false) {
if (this->keys_map->count(str) == 0) return false;
this->value = (*const_cast<t_config_enum_values*>(this->keys_map))[str];
return true;
@ -596,10 +596,12 @@ class ConfigBase
bool equals(ConfigBase &other);
t_config_option_keys diff(ConfigBase &other);
std::string serialize(const t_config_option_key &opt_key) const;
bool set_deserialize(const t_config_option_key &opt_key, std::string str);
bool set_deserialize(const t_config_option_key &opt_key, std::string str, bool append = false);
double get_abs_value(const t_config_option_key &opt_key);
double get_abs_value(const t_config_option_key &opt_key, double ratio_over);
void setenv_();
void load(const std::string &file);
void save(const std::string &file) const;
};
class DynamicConfig : public virtual ConfigBase

View File

@ -1383,6 +1383,12 @@ CLIConfigDef::CLIConfigDef()
def->cli = "info";
def->default_value = new ConfigOptionBool(false);
def = this->add("load", coStrings);
def->label = "Load config file";
def->tooltip = "Load configuration from the specified file. It can be used more than once to load options from multiple files.";
def->cli = "load";
def->default_value = new ConfigOptionStrings();
def = this->add("output", coString);
def->label = "Output File";
def->tooltip = "The file where the output will be written (if not specified, it will be based on the input file).";
@ -1395,6 +1401,12 @@ CLIConfigDef::CLIConfigDef()
def->cli = "rotate";
def->default_value = new ConfigOptionFloat(0);
def = this->add("save", coString);
def->label = "Save config file";
def->tooltip = "Save configuration to the specified file.";
def->cli = "save";
def->default_value = new ConfigOptionString();
def = this->add("scale", coFloat);
def->label = "Scale";
def->tooltip = "Scaling factor (default: 1).";

View File

@ -506,8 +506,10 @@ class CLIConfig
ConfigOptionBool export_pov;
ConfigOptionBool export_svg;
ConfigOptionBool info;
ConfigOptionStrings load;
ConfigOptionString output;
ConfigOptionFloat rotate;
ConfigOptionString save;
ConfigOptionFloat scale;
CLIConfig() : ConfigBase(), StaticConfig() {
@ -520,8 +522,10 @@ class CLIConfig
OPT_PTR(export_pov);
OPT_PTR(export_svg);
OPT_PTR(info);
OPT_PTR(load);
OPT_PTR(output);
OPT_PTR(rotate);
OPT_PTR(save);
OPT_PTR(scale);
return NULL;

View File

@ -38,6 +38,8 @@
void normalize();
%name{setenv} void setenv_();
double min_object_distance();
%name{_load} void load(std::string file);
void save(std::string file);
};
%name{Slic3r::Config::Static} class StaticPrintConfig {
@ -84,6 +86,8 @@
%};
%name{setenv} void setenv_();
double min_object_distance();
%name{_load} void load(std::string file);
void save(std::string file);
};
%package{Slic3r::Config};