~ubuntu-branches/ubuntu/utopic/slic3r/utopic

« back to all changes in this revision

Viewing changes to xs/src/Config.hpp

  • Committer: Package Import Robot
  • Author(s): Chow Loong Jin
  • Date: 2014-06-17 01:27:26 UTC
  • Revision ID: package-import@ubuntu.com-20140617012726-2wrs4zdo251nr4vg
Tags: upstream-1.1.4+dfsg
ImportĀ upstreamĀ versionĀ 1.1.4+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#ifndef slic3r_Config_hpp_
 
2
#define slic3r_Config_hpp_
 
3
 
 
4
#include <map>
 
5
#include <climits>
 
6
#include <cstdio>
 
7
#include <cstdlib>
 
8
#include <iostream>
 
9
#include <stdexcept>
 
10
#include <string>
 
11
#include <vector>
 
12
#include <myinit.h>
 
13
#include "Point.hpp"
 
14
 
 
15
namespace Slic3r {
 
16
 
 
17
typedef std::string t_config_option_key;
 
18
typedef std::vector<std::string> t_config_option_keys;
 
19
 
 
20
class ConfigOption {
 
21
    public:
 
22
    virtual ~ConfigOption() {};
 
23
    virtual std::string serialize() const = 0;
 
24
    virtual bool deserialize(std::string str) = 0;
 
25
    virtual int getInt() const { return 0; };
 
26
    virtual void setInt(int val) {};
 
27
};
 
28
 
 
29
template <class T>
 
30
class ConfigOptionVector
 
31
{
 
32
    public:
 
33
    virtual ~ConfigOptionVector() {};
 
34
    std::vector<T> values;
 
35
    
 
36
    T get_at(size_t i) const {
 
37
        try {
 
38
            return this->values.at(i);
 
39
        } catch (const std::out_of_range& oor) {
 
40
            return this->values.front();
 
41
        }
 
42
    };
 
43
};
 
44
 
 
45
class ConfigOptionFloat : public ConfigOption
 
46
{
 
47
    public:
 
48
    double value;  // use double instead of float for preserving compatibility with values coming from Perl
 
49
    ConfigOptionFloat() : value(0) {};
 
50
    
 
51
    operator double() const { return this->value; };
 
52
    
 
53
    std::string serialize() const {
 
54
        std::ostringstream ss;
 
55
        ss << this->value;
 
56
        return ss.str();
 
57
    };
 
58
    
 
59
    bool deserialize(std::string str) {
 
60
        this->value = ::atof(str.c_str());
 
61
        return true;
 
62
    };
 
63
};
 
64
 
 
65
class ConfigOptionFloats : public ConfigOption, public ConfigOptionVector<double>
 
66
{
 
67
    public:
 
68
    
 
69
    std::string serialize() const {
 
70
        std::ostringstream ss;
 
71
        for (std::vector<double>::const_iterator it = this->values.begin(); it != this->values.end(); ++it) {
 
72
            if (it - this->values.begin() != 0) ss << ",";
 
73
            ss << *it;
 
74
        }
 
75
        return ss.str();
 
76
    };
 
77
    
 
78
    bool deserialize(std::string str) {
 
79
        this->values.clear();
 
80
        std::istringstream is(str);
 
81
        std::string item_str;
 
82
        while (std::getline(is, item_str, ',')) {
 
83
            this->values.push_back(::atof(item_str.c_str()));
 
84
        }
 
85
        return true;
 
86
    };
 
87
};
 
88
 
 
89
class ConfigOptionInt : public ConfigOption
 
90
{
 
91
    public:
 
92
    int value;
 
93
    ConfigOptionInt() : value(0) {};
 
94
    
 
95
    operator int() const { return this->value; };
 
96
    int getInt() const { return this->value; };
 
97
    void setInt(int val) { this->value = val; };
 
98
    
 
99
    std::string serialize() const {
 
100
        std::ostringstream ss;
 
101
        ss << this->value;
 
102
        return ss.str();
 
103
    };
 
104
    
 
105
    bool deserialize(std::string str) {
 
106
        this->value = ::atoi(str.c_str());
 
107
        return true;
 
108
    };
 
109
};
 
110
 
 
111
class ConfigOptionInts : public ConfigOption, public ConfigOptionVector<int>
 
112
{
 
113
    public:
 
114
    
 
115
    std::string serialize() const {
 
116
        std::ostringstream ss;
 
117
        for (std::vector<int>::const_iterator it = this->values.begin(); it != this->values.end(); ++it) {
 
118
            if (it - this->values.begin() != 0) ss << ",";
 
119
            ss << *it;
 
120
        }
 
121
        return ss.str();
 
122
    };
 
123
    
 
124
    bool deserialize(std::string str) {
 
125
        this->values.clear();
 
126
        std::istringstream is(str);
 
127
        std::string item_str;
 
128
        while (std::getline(is, item_str, ',')) {
 
129
            this->values.push_back(::atoi(item_str.c_str()));
 
130
        }
 
131
        return true;
 
132
    };
 
133
};
 
134
 
 
135
class ConfigOptionString : public ConfigOption
 
136
{
 
137
    public:
 
138
    std::string value;
 
139
    ConfigOptionString() : value("") {};
 
140
    
 
141
    operator std::string() const { return this->value; };
 
142
    
 
143
    std::string serialize() const {
 
144
        std::string str = this->value;
 
145
        
 
146
        // s/\R/\\n/g
 
147
        size_t pos = 0;
 
148
        while ((pos = str.find("\n", pos)) != std::string::npos || (pos = str.find("\r", pos)) != std::string::npos) {
 
149
            str.replace(pos, 1, "\\n");
 
150
            pos += 2; // length of "\\n"
 
151
        }
 
152
        
 
153
        return str; 
 
154
    };
 
155
    
 
156
    bool deserialize(std::string str) {
 
157
        // s/\\n/\n/g
 
158
        size_t pos = 0;
 
159
        while ((pos = str.find("\\n", pos)) != std::string::npos) {
 
160
            str.replace(pos, 2, "\n");
 
161
            pos += 1; // length of "\n"
 
162
        }
 
163
        
 
164
        this->value = str;
 
165
        return true;
 
166
    };
 
167
};
 
168
 
 
169
// semicolon-separated strings
 
170
class ConfigOptionStrings : public ConfigOption, public ConfigOptionVector<std::string>
 
171
{
 
172
    public:
 
173
    
 
174
    std::string serialize() const {
 
175
        std::ostringstream ss;
 
176
        for (std::vector<std::string>::const_iterator it = this->values.begin(); it != this->values.end(); ++it) {
 
177
            if (it - this->values.begin() != 0) ss << ";";
 
178
            ss << *it;
 
179
        }
 
180
        return ss.str();
 
181
    };
 
182
    
 
183
    bool deserialize(std::string str) {
 
184
        this->values.clear();
 
185
        std::istringstream is(str);
 
186
        std::string item_str;
 
187
        while (std::getline(is, item_str, ';')) {
 
188
            this->values.push_back(item_str);
 
189
        }
 
190
        return true;
 
191
    };
 
192
};
 
193
 
 
194
class ConfigOptionPercent : public ConfigOption
 
195
{
 
196
    public:
 
197
    double value;
 
198
    ConfigOptionPercent() : value(0) {};
 
199
    
 
200
    double get_abs_value(double ratio_over) const {
 
201
        return ratio_over * this->value / 100;
 
202
    };
 
203
    
 
204
    std::string serialize() const {
 
205
        std::ostringstream ss;
 
206
        ss << this->value;
 
207
        std::string s(ss.str());
 
208
        s += "%";
 
209
        return s;
 
210
    };
 
211
    
 
212
    bool deserialize(std::string str) {
 
213
        // don't try to parse the trailing % since it's optional
 
214
        int res = sscanf(str.c_str(), "%lf", &this->value);
 
215
        return res == 1;
 
216
    };
 
217
};
 
218
 
 
219
class ConfigOptionFloatOrPercent : public ConfigOption
 
220
{
 
221
    public:
 
222
    double value;
 
223
    bool percent;
 
224
    ConfigOptionFloatOrPercent() : value(0), percent(false) {};
 
225
    
 
226
    double get_abs_value(double ratio_over) const {
 
227
        if (this->percent) {
 
228
            return ratio_over * this->value / 100;
 
229
        } else {
 
230
            return this->value;
 
231
        }
 
232
    };
 
233
    
 
234
    std::string serialize() const {
 
235
        std::ostringstream ss;
 
236
        ss << this->value;
 
237
        std::string s(ss.str());
 
238
        if (this->percent) s += "%";
 
239
        return s;
 
240
    };
 
241
    
 
242
    bool deserialize(std::string str) {
 
243
        if (str.find_first_of("%") != std::string::npos) {
 
244
            int res = sscanf(str.c_str(), "%lf%%", &this->value);
 
245
            if (res == 0) return false;
 
246
            this->percent = true;
 
247
        } else {
 
248
            this->value = ::atof(str.c_str());
 
249
            this->percent = false;
 
250
        }
 
251
        return true;
 
252
    };
 
253
};
 
254
 
 
255
class ConfigOptionPoint : public ConfigOption
 
256
{
 
257
    public:
 
258
    Pointf point;
 
259
    ConfigOptionPoint() : point(Pointf(0,0)) {};
 
260
    
 
261
    operator Pointf() const { return this->point; };
 
262
    
 
263
    std::string serialize() const {
 
264
        std::ostringstream ss;
 
265
        ss << this->point.x;
 
266
        ss << ",";
 
267
        ss << this->point.y;
 
268
        return ss.str();
 
269
    };
 
270
    
 
271
    bool deserialize(std::string str) {
 
272
        if (strncmp(str.c_str(), "0x", 2) == 0) {
 
273
            this->point.x = 0;
 
274
            int res = sscanf(str.c_str()+2, "%lf", &this->point.y);
 
275
            return res == 1;
 
276
        } else {
 
277
            int res = sscanf(str.c_str(), "%lf%*1[,x]%lf", &this->point.x, &this->point.y);
 
278
            return res == 2;
 
279
        }
 
280
    };
 
281
};
 
282
 
 
283
class ConfigOptionPoints : public ConfigOption, public ConfigOptionVector<Pointf>
 
284
{
 
285
    public:
 
286
    
 
287
    std::string serialize() const {
 
288
        std::ostringstream ss;
 
289
        for (Pointfs::const_iterator it = this->values.begin(); it != this->values.end(); ++it) {
 
290
            if (it - this->values.begin() != 0) ss << ",";
 
291
            ss << it->x;
 
292
            ss << "x";
 
293
            ss << it->y;
 
294
        }
 
295
        return ss.str();
 
296
    };
 
297
    
 
298
    bool deserialize(std::string str) {
 
299
        std::vector<Pointf> values;
 
300
        std::istringstream is(str);
 
301
        std::string point_str;
 
302
        while (std::getline(is, point_str, ',')) {
 
303
            Pointf point;
 
304
            if (strncmp(point_str.c_str(), "0x", 2) == 0) {
 
305
                // if string starts with "0x", only apply sscanf() to the second coordinate
 
306
                // otherwise it would parse the string as a hex number
 
307
                point.x = 0;
 
308
                int res = sscanf(point_str.c_str()+2, "%lf", &point.y);
 
309
                if (res != 1) return false;
 
310
            } else {
 
311
                int res = sscanf(point_str.c_str(), "%lfx%lf", &point.x, &point.y);
 
312
                if (res != 2) return false;
 
313
            }
 
314
            values.push_back(point);
 
315
        }
 
316
        this->values = values;
 
317
        return true;
 
318
    };
 
319
};
 
320
 
 
321
class ConfigOptionBool : public ConfigOption
 
322
{
 
323
    public:
 
324
    bool value;
 
325
    ConfigOptionBool() : value(false) {};
 
326
    
 
327
    operator bool() const { return this->value; };
 
328
    
 
329
    std::string serialize() const {
 
330
        return std::string(this->value ? "1" : "0");
 
331
    };
 
332
    
 
333
    bool deserialize(std::string str) {
 
334
        this->value = (str.compare("1") == 0);
 
335
        return true;
 
336
    };
 
337
};
 
338
 
 
339
class ConfigOptionBools : public ConfigOption, public ConfigOptionVector<bool>
 
340
{
 
341
    public:
 
342
    
 
343
    std::string serialize() const {
 
344
        std::ostringstream ss;
 
345
        for (std::vector<bool>::const_iterator it = this->values.begin(); it != this->values.end(); ++it) {
 
346
            if (it - this->values.begin() != 0) ss << ",";
 
347
            ss << (*it ? "1" : "0");
 
348
        }
 
349
        return ss.str();
 
350
    };
 
351
    
 
352
    bool deserialize(std::string str) {
 
353
        this->values.clear();
 
354
        std::istringstream is(str);
 
355
        std::string item_str;
 
356
        while (std::getline(is, item_str, ',')) {
 
357
            this->values.push_back(item_str.compare("1") == 0);
 
358
        }
 
359
        return true;
 
360
    };
 
361
};
 
362
 
 
363
typedef std::map<std::string,int> t_config_enum_values;
 
364
 
 
365
template <class T>
 
366
class ConfigOptionEnum : public ConfigOption
 
367
{
 
368
    public:
 
369
    T value;
 
370
    
 
371
    operator T() const { return this->value; };
 
372
    
 
373
    std::string serialize() const {
 
374
        t_config_enum_values enum_keys_map = ConfigOptionEnum<T>::get_enum_values();
 
375
        for (t_config_enum_values::iterator it = enum_keys_map.begin(); it != enum_keys_map.end(); ++it) {
 
376
            if (it->second == static_cast<int>(this->value)) return it->first;
 
377
        }
 
378
        return "";
 
379
    };
 
380
 
 
381
    bool deserialize(std::string str) {
 
382
        t_config_enum_values enum_keys_map = ConfigOptionEnum<T>::get_enum_values();
 
383
        if (enum_keys_map.count(str) == 0) return false;
 
384
        this->value = static_cast<T>(enum_keys_map[str]);
 
385
        return true;
 
386
    };
 
387
 
 
388
    static t_config_enum_values get_enum_values();
 
389
};
 
390
 
 
391
/* We use this one in DynamicConfig objects, otherwise it's better to use
 
392
   the specialized ConfigOptionEnum<T> containers. */
 
393
class ConfigOptionEnumGeneric : public ConfigOption
 
394
{
 
395
    public:
 
396
    int value;
 
397
    t_config_enum_values* keys_map;
 
398
    
 
399
    operator int() const { return this->value; };
 
400
    
 
401
    std::string serialize() const {
 
402
        for (t_config_enum_values::iterator it = this->keys_map->begin(); it != this->keys_map->end(); ++it) {
 
403
            if (it->second == this->value) return it->first;
 
404
        }
 
405
        return "";
 
406
    };
 
407
 
 
408
    bool deserialize(std::string str) {
 
409
        if (this->keys_map->count(str) == 0) return false;
 
410
        this->value = (*this->keys_map)[str];
 
411
        return true;
 
412
    };
 
413
};
 
414
 
 
415
enum ConfigOptionType {
 
416
    coFloat,
 
417
    coFloats,
 
418
    coInt,
 
419
    coInts,
 
420
    coString,
 
421
    coStrings,
 
422
    coPercent,
 
423
    coFloatOrPercent,
 
424
    coPoint,
 
425
    coPoints,
 
426
    coBool,
 
427
    coBools,
 
428
    coEnum,
 
429
};
 
430
 
 
431
class ConfigOptionDef
 
432
{
 
433
    public:
 
434
    ConfigOptionType type;
 
435
    std::string label;
 
436
    std::string full_label;
 
437
    std::string category;
 
438
    std::string tooltip;
 
439
    std::string sidetext;
 
440
    std::string cli;
 
441
    t_config_option_key ratio_over;
 
442
    bool multiline;
 
443
    bool full_width;
 
444
    bool readonly;
 
445
    int height;
 
446
    int width;
 
447
    int min;
 
448
    int max;
 
449
    std::vector<t_config_option_key> aliases;
 
450
    std::vector<t_config_option_key> shortcut;
 
451
    std::vector<std::string> enum_values;
 
452
    std::vector<std::string> enum_labels;
 
453
    t_config_enum_values enum_keys_map;
 
454
    
 
455
    ConfigOptionDef() : multiline(false), full_width(false), readonly(false),
 
456
                        height(-1), width(-1), min(INT_MIN), max(INT_MAX) {};
 
457
};
 
458
 
 
459
typedef std::map<t_config_option_key,ConfigOptionDef> t_optiondef_map;
 
460
 
 
461
class ConfigBase
 
462
{
 
463
    public:
 
464
    t_optiondef_map* def;
 
465
    
 
466
    ConfigBase() : def(NULL) {};
 
467
    bool has(const t_config_option_key opt_key);
 
468
    virtual ConfigOption* option(const t_config_option_key opt_key, bool create = false) = 0;
 
469
    virtual const ConfigOption* option(const t_config_option_key opt_key) const = 0;
 
470
    virtual void keys(t_config_option_keys *keys) const = 0;
 
471
    void apply(const ConfigBase &other, bool ignore_nonexistent = false);
 
472
    std::string serialize(const t_config_option_key opt_key);
 
473
    bool set_deserialize(const t_config_option_key opt_key, std::string str);
 
474
    double get_abs_value(const t_config_option_key opt_key);
 
475
    double get_abs_value(const t_config_option_key opt_key, double ratio_over);
 
476
    
 
477
    #ifdef SLIC3RXS
 
478
    SV* as_hash();
 
479
    SV* get(t_config_option_key opt_key);
 
480
    SV* get_at(t_config_option_key opt_key, size_t i);
 
481
    bool set(t_config_option_key opt_key, SV* value);
 
482
    bool set_deserialize(const t_config_option_key opt_key, SV* str);
 
483
    #endif
 
484
};
 
485
 
 
486
class DynamicConfig : public ConfigBase
 
487
{
 
488
    public:
 
489
    DynamicConfig() {};
 
490
    DynamicConfig(const DynamicConfig& other);
 
491
    DynamicConfig& operator= (DynamicConfig other);
 
492
    void swap(DynamicConfig &other);
 
493
    ~DynamicConfig();
 
494
    template<class T> T* opt(const t_config_option_key opt_key, bool create = false);
 
495
    ConfigOption* option(const t_config_option_key opt_key, bool create = false);
 
496
    const ConfigOption* option(const t_config_option_key opt_key) const;
 
497
    void keys(t_config_option_keys *keys) const;
 
498
    void erase(const t_config_option_key opt_key);
 
499
    
 
500
    private:
 
501
    typedef std::map<t_config_option_key,ConfigOption*> t_options_map;
 
502
    t_options_map options;
 
503
};
 
504
 
 
505
class StaticConfig : public ConfigBase
 
506
{
 
507
    public:
 
508
    void keys(t_config_option_keys *keys) const;
 
509
    virtual ConfigOption* option(const t_config_option_key opt_key, bool create = false) = 0;
 
510
    const ConfigOption* option(const t_config_option_key opt_key) const;
 
511
    
 
512
    #ifdef SLIC3RXS
 
513
    bool set(t_config_option_key opt_key, SV* value);
 
514
    #endif
 
515
};
 
516
 
 
517
}
 
518
 
 
519
#endif