diff options
author | bubnikv <bubnikv@gmail.com> | 2016-11-01 15:41:24 +0300 |
---|---|---|
committer | bubnikv <bubnikv@gmail.com> | 2016-11-01 15:41:24 +0300 |
commit | 3d3654707b97f679037cb66c2143338cf8baf917 (patch) | |
tree | e13ed4e8725d1f4d4c1b713f518ac5167e72e16a /xs/src/libslic3r/Config.cpp | |
parent | 4e66ed81d26774a6196259dee35a5da0c678d081 (diff) |
Added "Notes" page to the filament configuration.
Added "filament_max_volumetric_speed", a cap on the maximum volumetric
extrusion role, filament specific. This is very useful when mixing
rigid filament with a soft filament.
Extended the import / export of multi-string values into configuration
values, including the test cases. Multi-line strings will be enclosed
into quotes, quotes escaped using a C-style escape sequences. Single
word strings could still be stored without quotes.
Diffstat (limited to 'xs/src/libslic3r/Config.cpp')
-rw-r--r-- | xs/src/libslic3r/Config.cpp | 165 |
1 files changed, 159 insertions, 6 deletions
diff --git a/xs/src/libslic3r/Config.cpp b/xs/src/libslic3r/Config.cpp index 39c0da2bb..cdeee4dd8 100644 --- a/xs/src/libslic3r/Config.cpp +++ b/xs/src/libslic3r/Config.cpp @@ -8,6 +8,159 @@ namespace Slic3r { +std::string escape_string_cstyle(const std::string &str) +{ + // Allocate a buffer twice the input string length, + // so the output will fit even if all input characters get escaped. + std::vector<char> out(str.size() * 2, 0); + char *outptr = out.data(); + for (size_t i = 0; i < str.size(); ++ i) { + char c = str[i]; + if (c == '\n' || c == '\r') { + (*outptr ++) = '\\'; + (*outptr ++) = 'n'; + } else + (*outptr ++) = c; + } + return std::string(out.data(), outptr - out.data()); +} + +std::string escape_strings_cstyle(const std::vector<std::string> &strs) +{ + // 1) Estimate the output buffer size to avoid buffer reallocation. + size_t outbuflen = 0; + for (size_t i = 0; i < strs.size(); ++ i) + // Reserve space for every character escaped + quotes + semicolon. + outbuflen += strs[i].size() * 2 + 3; + // 2) Fill in the buffer. + std::vector<char> out(outbuflen, 0); + char *outptr = out.data(); + for (size_t j = 0; j < strs.size(); ++ j) { + if (j > 0) + // Separate the strings. + (*outptr ++) = ';'; + const std::string &str = strs[j]; + // Is the string simple or complex? Complex string contains spaces, tabs, new lines and other + // escapable characters. Empty string shall be quoted as well, if it is the only string in strs. + bool should_quote = strs.size() == 1 && str.empty(); + for (size_t i = 0; i < str.size(); ++ i) { + char c = str[i]; + if (c == ' ' || c == '\t' || c == '\\' || c == '"' || c == '\r' || c == '\n') { + should_quote = true; + break; + } + } + if (should_quote) { + (*outptr ++) = '"'; + for (size_t i = 0; i < str.size(); ++ i) { + char c = str[i]; + if (c == '\\' || c == '"') { + (*outptr ++) = '\\'; + (*outptr ++) = c; + } else if (c == '\n' || c == '\r') { + (*outptr ++) = '\\'; + (*outptr ++) = 'n'; + } else + (*outptr ++) = c; + } + (*outptr ++) = '"'; + } else { + memcpy(outptr, str.data(), str.size()); + outptr += str.size(); + } + } + return std::string(out.data(), outptr - out.data()); +} + +bool unescape_string_cstyle(const std::string &str, std::string &str_out) +{ + std::vector<char> out(str.size(), 0); + char *outptr = out.data(); + for (size_t i = 0; i < str.size(); ++ i) { + char c = str[i]; + if (c == '\\') { + if (++ i == str.size()) + return false; + c = str[i]; + if (c == 'n') + (*outptr ++) = '\n'; + } else + (*outptr ++) = c; + } + str_out.assign(out.data(), outptr - out.data()); + return true; +} + +bool unescape_strings_cstyle(const std::string &str, std::vector<std::string> &out) +{ + out.clear(); + if (str.empty()) + return true; + + size_t i = 0; + for (;;) { + // Skip white spaces. + char c = str[i]; + while (c == ' ' || c == '\t') { + if (++ i == str.size()) + return true; + c = str[i]; + } + // Start of a word. + std::vector<char> buf; + buf.reserve(16); + // Is it enclosed in quotes? + c = str[i]; + if (c == '"') { + // Complex case, string is enclosed in quotes. + for (++ i; i < str.size(); ++ i) { + c = str[i]; + if (c == '"') { + // End of string. + break; + } + if (c == '\\') { + if (++ i == str.size()) + return false; + c = str[i]; + if (c == 'n') + c = '\n'; + } + buf.push_back(c); + } + if (i == str.size()) + return false; + ++ i; + } else { + for (; i < str.size(); ++ i) { + c = str[i]; + if (c == ';') + break; + buf.push_back(c); + } + } + // Store the string into the output vector. + out.push_back(std::string(buf.data(), buf.size())); + if (i == str.size()) + break; + // Skip white spaces. + c = str[i]; + while (c == ' ' || c == '\t') { + if (++ i == str.size()) + // End of string. This is correct. + return true; + c = str[i]; + } + if (c != ';') + return false; + if (++ i == str.size()) { + // Emit one additional empty string. + out.push_back(std::string()); + return true; + } + } +} + bool operator== (const ConfigOption &a, const ConfigOption &b) { @@ -116,16 +269,16 @@ ConfigBase::set_deserialize(const t_config_option_key &opt_key, std::string str) // Return an absolute value of a possibly relative config variable. // For example, return absolute infill extrusion width, either from an absolute value, or relative to the layer height. double -ConfigBase::get_abs_value(const t_config_option_key &opt_key) { - ConfigOption* opt = this->option(opt_key, false); - if (ConfigOptionFloatOrPercent* optv = dynamic_cast<ConfigOptionFloatOrPercent*>(opt)) { +ConfigBase::get_abs_value(const t_config_option_key &opt_key) const { + const ConfigOption* opt = this->option(opt_key); + if (const ConfigOptionFloatOrPercent* optv = dynamic_cast<const ConfigOptionFloatOrPercent*>(opt)) { // get option definition const ConfigOptionDef* def = this->def->get(opt_key); assert(def != NULL); // compute absolute value over the absolute value of the base option return optv->get_abs_value(this->get_abs_value(def->ratio_over)); - } else if (ConfigOptionFloat* optv = dynamic_cast<ConfigOptionFloat*>(opt)) { + } else if (const ConfigOptionFloat* optv = dynamic_cast<const ConfigOptionFloat*>(opt)) { return optv->value; } else { throw "Not a valid option type for get_abs_value()"; @@ -135,9 +288,9 @@ ConfigBase::get_abs_value(const t_config_option_key &opt_key) { // Return an absolute value of a possibly relative config variable. // For example, return absolute infill extrusion width, either from an absolute value, or relative to a provided value. double -ConfigBase::get_abs_value(const t_config_option_key &opt_key, double ratio_over) { +ConfigBase::get_abs_value(const t_config_option_key &opt_key, double ratio_over) const { // get stored option value - ConfigOptionFloatOrPercent* opt = dynamic_cast<ConfigOptionFloatOrPercent*>(this->option(opt_key)); + const ConfigOptionFloatOrPercent* opt = dynamic_cast<const ConfigOptionFloatOrPercent*>(this->option(opt_key)); assert(opt != NULL); // compute absolute value |