Welcome to mirror list, hosted at ThFree Co, Russian Federation.

PlaceholderParser.cpp « libslic3r « src « xs - github.com/supermerill/SuperSlicer.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 4a73cd12b2abf6598ca27028ab01982fcd2ac311 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
#include "PlaceholderParser.hpp"
#include <ctime>
#include <iomanip>
#include <sstream>
#include <unistd.h>  // provides **environ

extern char **environ;

namespace Slic3r {

PlaceholderParser::PlaceholderParser()
{
    this->set("version", SLIC3R_VERSION);
    this->apply_env_variables();
    this->update_timestamp();
}

void
PlaceholderParser::update_timestamp()
{
    time_t rawtime;
    time(&rawtime);
    struct tm* timeinfo = localtime(&rawtime);
    
    {
        std::ostringstream ss;
        ss << (1900 + timeinfo->tm_year);
        ss << std::setw(2) << std::setfill('0') << (1 + timeinfo->tm_mon);
        ss << std::setw(2) << std::setfill('0') << timeinfo->tm_mday;
        ss << "-";
        ss << std::setw(2) << std::setfill('0') << timeinfo->tm_hour;
        ss << std::setw(2) << std::setfill('0') << timeinfo->tm_min;
        ss << std::setw(2) << std::setfill('0') << timeinfo->tm_sec;
        this->set("timestamp", ss.str());
    }
    this->set("year",   1900 + timeinfo->tm_year);
    this->set("month",  1 + timeinfo->tm_mon);
    this->set("day",    timeinfo->tm_mday);
    this->set("hour",   timeinfo->tm_hour);
    this->set("minute", timeinfo->tm_min);
    this->set("second", timeinfo->tm_sec);
}

void PlaceholderParser::apply_config(const DynamicPrintConfig &config)
{
    t_config_option_keys opt_keys = config.keys();
    for (t_config_option_keys::const_iterator i = opt_keys.begin(); i != opt_keys.end(); ++i) {
        const t_config_option_key &opt_key = *i;
        const ConfigOptionDef* def = config.def->get(opt_key);
        if (def->multiline) continue;
        
        const ConfigOption* opt = config.option(opt_key);
        if (const ConfigOptionVectorBase* optv = dynamic_cast<const ConfigOptionVectorBase*>(opt)) {
            // set placeholders for options with multiple values
            // TODO: treat [bed_shape] as single, not multiple
            this->set(opt_key, optv->vserialize());
        } else if (const ConfigOptionPoint* optp = dynamic_cast<const ConfigOptionPoint*>(opt)) {
            this->set(opt_key, optp->serialize());
            
            Pointf val = *optp;
            this->set(opt_key + "_X", val.x);
            this->set(opt_key + "_Y", val.y);
        } else {
            // set single-value placeholders
            this->set(opt_key, opt->serialize());
        }
    }
}

void
PlaceholderParser::apply_env_variables()
{
    for (char** env = environ; *env; env++) {
        if (strncmp(*env, "SLIC3R_", 7) == 0) {
            std::stringstream ss(*env);
            std::string key, value;
            std::getline(ss, key, '=');
            ss >> value;
            
            this->set(key, value);
        }
    }
}

void
PlaceholderParser::set(const std::string &key, const std::string &value)
{
    this->_single[key] = value;
    this->_multiple.erase(key);
}

void
PlaceholderParser::set(const std::string &key, int value)
{
    std::ostringstream ss;
    ss << value;
    this->set(key, ss.str());
}

void
PlaceholderParser::set(const std::string &key, std::vector<std::string> values)
{
    if (values.empty()) {
        this->_multiple.erase(key);
        this->_single.erase(key);
    } else {
        this->_multiple[key] = values;
        this->_single[key] = values.front();
    }
}

std::string
PlaceholderParser::process(std::string str) const
{
    // replace single options, like [foo]
    for (t_strstr_map::const_iterator it = this->_single.begin(); it != this->_single.end(); ++it) {
        std::stringstream ss;
        ss << '[' << it->first << ']';
        this->find_and_replace(str, ss.str(), it->second);
    }
    
    // replace multiple options like [foo_0] by looping until we have enough values
    // or until a previous match was found (this handles non-existing indices reasonably
    // without a regex)
    for (t_strstrs_map::const_iterator it = this->_multiple.begin(); it != this->_multiple.end(); ++it) {
        const std::vector<std::string> &values = it->second;
        bool found = false;
        for (size_t i = 0; (i < values.size()) || found; ++i) {
            std::stringstream ss;
            ss << '[' << it->first << '_' << i << ']';
            if (i < values.size()) {
                found = this->find_and_replace(str, ss.str(), values[i]);
            } else {
                found = this->find_and_replace(str, ss.str(), values.front());
            }
        }
    }
    
    return str;
}

bool
PlaceholderParser::find_and_replace(std::string &source, std::string const &find, std::string const &replace) const
{
    bool found = false;
    for (std::string::size_type i = 0; (i = source.find(find, i)) != std::string::npos; ) {
        source.replace(i, find.length(), replace);
        i += replace.length();
        found = true;
    }
    return found;
}

#ifdef SLIC3RXS
REGISTER_CLASS(PlaceholderParser, "GCode::PlaceholderParser");
#endif

}