Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/tutorial/src/orxonox/core/ConfigValueContainer.cc @ 859

Last change on this file since 859 was 859, checked in by landauf, 16 years ago

more or less a copy of the trunk

File size: 43.9 KB
Line 
1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *
4 *
5 *   License notice:
6 *
7 *   This program is free software; you can redistribute it and/or
8 *   modify it under the terms of the GNU General Public License
9 *   as published by the Free Software Foundation; either version 2
10 *   of the License, or (at your option) any later version.
11 *
12 *   This program is distributed in the hope that it will be useful,
13 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
14 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 *   GNU General Public License for more details.
16 *
17 *   You should have received a copy of the GNU General Public License
18 *   along with this program; if not, write to the Free Software
19 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
20 *
21 *   Author:
22 *      Fabian 'x3n' Landau
23 *   Co-authors:
24 *      ...
25 *
26 */
27
28#include <fstream>
29
30#include "util/Tokenizer.h"
31#include "util/Convert.h"
32#include "ConfigValueContainer.h"
33
34#define CONFIGFILEPATH "orxonox.ini"
35
36namespace orxonox
37{
38    /**
39        @brief Constructor: Converts the default-value to a string, checks the config-file for a changed value, sets the intern value variable.
40        @param value This is only needed to determine the right type.
41        @param classname The name of the class the variable belongs to
42        @param varname The name of the variable
43        @param defvalue The default-value
44    */
45    ConfigValueContainer::ConfigValueContainer(const std::string& classname, const std::string& varname, int defvalue)
46    {
47        this->bAddedDescription_ = false;
48        this->classname_ = classname;
49        this->varname_ = varname;
50        this->type_ = VT_Int;
51
52        ConvertValue(&this->defvalueString_, defvalue, std::string("0"));           // Try to convert the default-value to a string
53        this->searchConfigFileLine();                                               // Search the entry in the config-file
54
55        std::string valueString = this->parseValueString();                         // Parses the value string from the config-file-entry
56        if (!this->parseSting(valueString, defvalue))                               // Try to convert the string to a value
57            this->resetConfigFileEntry();                                           // The conversion failed
58    }
59
60    /**
61        @brief Constructor: Converts the default-value to a string, checks the config-file for a changed value, sets the intern value variable.
62        @param value This is only needed to determine the right type.
63        @param classname The name of the class the variable belongs to
64        @param varname The name of the variable
65        @param defvalue The default-value
66    */
67    ConfigValueContainer::ConfigValueContainer(const std::string& classname, const std::string& varname, unsigned int defvalue)
68    {
69        this->bAddedDescription_ = false;
70        this->classname_ = classname;
71        this->varname_ = varname;
72        this->type_ = VT_uInt;
73
74        ConvertValue(&this->defvalueString_, defvalue, std::string("0"));           // Try to convert the default-value to a string
75        this->searchConfigFileLine();                                               // Search the entry in the config-file
76
77        std::string valueString = this->parseValueString();                         // Parses the value string from the config-file-entry
78        if (!this->parseSting(valueString, defvalue))                               // Try to convert the string to a value
79            this->resetConfigFileEntry();                                           // The conversion failed
80    }
81
82    /**
83        @brief Constructor: Converts the default-value to a string, checks the config-file for a changed value, sets the intern value variable.
84        @param value This is only needed to determine the right type.
85        @param classname The name of the class the variable belongs to
86        @param varname The name of the variable
87        @param defvalue The default-value
88    */
89    ConfigValueContainer::ConfigValueContainer(const std::string& classname, const std::string& varname, char defvalue)
90    {
91        this->bAddedDescription_ = false;
92        this->classname_ = classname;
93        this->varname_ = varname;
94        this->type_ = VT_Char;
95
96        ConvertValue(&this->defvalueString_, (int)defvalue, std::string("0"));      // Try to convert the default-value to a string
97        this->searchConfigFileLine();                                               // Search the entry in the config-file
98
99        std::string valueString = this->parseValueString();                         // Parses the value string from the config-file-entry
100        if (!this->parseSting(valueString, defvalue))                               // Try to convert the string to a value
101            this->resetConfigFileEntry();                                           // The conversion failed
102    }
103
104    /**
105        @brief Constructor: Converts the default-value to a string, checks the config-file for a changed value, sets the intern value variable.
106        @param value This is only needed to determine the right type.
107        @param classname The name of the class the variable belongs to
108        @param varname The name of the variable
109        @param defvalue The default-value
110    */
111    ConfigValueContainer::ConfigValueContainer(const std::string& classname, const std::string& varname, unsigned char defvalue)
112    {
113        this->bAddedDescription_ = false;
114        this->classname_ = classname;
115        this->varname_ = varname;
116        this->type_ = VT_uChar;
117
118        ConvertValue(&this->defvalueString_, (unsigned int)defvalue, std::string("0"));     // Try to convert the default-value to a string
119        this->searchConfigFileLine();                                               // Search the entry in the config-file
120
121        std::string valueString = this->parseValueString();                         // Parses the value string from the config-file-entry
122        if (!this->parseSting(valueString, defvalue))                               // Try to convert the string to a value
123            this->resetConfigFileEntry();                                           // The conversion failed
124    }
125
126    /**
127        @brief Constructor: Converts the default-value to a string, checks the config-file for a changed value, sets the intern value variable.
128        @param value This is only needed to determine the right type.
129        @param classname The name of the class the variable belongs to
130        @param varname The name of the variable
131        @param defvalue The default-value
132    */
133    ConfigValueContainer::ConfigValueContainer(const std::string& classname, const std::string& varname, float defvalue)
134    {
135        this->bAddedDescription_ = false;
136        this->classname_ = classname;
137        this->varname_ = varname;
138        this->type_ = VT_Float;
139
140        ConvertValue(&this->defvalueString_, defvalue, std::string("0.000000"));    // Try to convert the default-value to a string
141        this->searchConfigFileLine();                                               // Search the entry in the config-file
142
143        std::string valueString = this->parseValueString();                         // Parses the value string from the config-file-entry
144        if (!this->parseSting(valueString, defvalue))                               // Try to convert the string to a value
145            this->resetConfigFileEntry();                                           // The conversion failed
146    }
147
148    /**
149        @brief Constructor: Converts the default-value to a string, checks the config-file for a changed value, sets the intern value variable.
150        @param value This is only needed to determine the right type.
151        @param classname The name of the class the variable belongs to
152        @param varname The name of the variable
153        @param defvalue The default-value
154    */
155    ConfigValueContainer::ConfigValueContainer(const std::string& classname, const std::string& varname, double defvalue)
156    {
157        this->bAddedDescription_ = false;
158        this->classname_ = classname;
159        this->varname_ = varname;
160        this->type_ = VT_Double;
161
162        ConvertValue(&this->defvalueString_, defvalue, std::string("0.000000"));    // Try to convert the default-value to a string
163        this->searchConfigFileLine();                                               // Search the entry in the config-file
164
165        std::string valueString = this->parseValueString();                         // Parses the value string from the config-file-entry
166        if (!this->parseSting(valueString, defvalue))                               // Try to convert the string to a value
167            this->resetConfigFileEntry();                                           // The conversion failed
168    }
169
170    /**
171        @brief Constructor: Converts the default-value to a string, checks the config-file for a changed value, sets the intern value variable.
172        @param value This is only needed to determine the right type.
173        @param classname The name of the class the variable belongs to
174        @param varname The name of the variable
175        @param defvalue The default-value
176    */
177    ConfigValueContainer::ConfigValueContainer(const std::string& classname, const std::string& varname, long double defvalue)
178    {
179        this->bAddedDescription_ = false;
180        this->classname_ = classname;
181        this->varname_ = varname;
182        this->type_ = VT_LongDouble;
183
184        ConvertValue(&this->defvalueString_, defvalue, std::string("0.000000"));    // Try to convert the default-value to a string
185        this->searchConfigFileLine();                                               // Search the entry in the config-file
186
187        std::string valueString = this->parseValueString();                         // Parses the value string from the config-file-entry
188        if (!this->parseSting(valueString, defvalue))                               // Try to convert the string to a value
189            this->resetConfigFileEntry();                                           // The conversion failed
190    }
191
192    /**
193        @brief Constructor: Converts the default-value to a string, checks the config-file for a changed value, sets the intern value variable.
194        @param value This is only needed to determine the right type.
195        @param classname The name of the class the variable belongs to
196        @param varname The name of the variable
197        @param defvalue The default-value
198    */
199    ConfigValueContainer::ConfigValueContainer(const std::string& classname, const std::string& varname, bool defvalue)
200    {
201        this->bAddedDescription_ = false;
202        this->classname_ = classname;
203        this->varname_ = varname;
204        this->type_ = VT_Bool;
205
206        // Convert the default-value from bool to string
207        if (defvalue)
208            this->defvalueString_ = "true";
209        else
210            this->defvalueString_ = "false";
211
212        this->searchConfigFileLine();                                               // Search the entry in the config-file
213        std::string valueString = this->parseValueString();                         // Parses the value string from the config-file-entry
214        if (!this->parseSting(valueString, defvalue))                               // Try to convert the string to a value
215            this->resetConfigFileEntry();                                           // The conversion failed
216    }
217
218    /**
219        @brief Constructor: Converts the default-value to a string, checks the config-file for a changed value, sets the intern value variable.
220        @param value This is only needed to determine the right type.
221        @param classname The name of the class the variable belongs to
222        @param varname The name of the variable
223        @param defvalue The default-value
224    */
225    ConfigValueContainer::ConfigValueContainer(const std::string& classname, const std::string& varname, const std::string& defvalue)
226    {
227        this->bAddedDescription_ = false;
228        this->classname_ = classname;
229        this->varname_ = varname;
230        this->type_ = VT_String;
231
232        this->defvalueString_ = "\"" + defvalue + "\"";                             // Convert the string to a "config-file-string" with quotes
233        this->searchConfigFileLine();                                               // Search the entry in the config-file
234        std::string valueString = this->parseValueString(false);                    // Parses the value string from the config-file-entry
235        if (!this->parseSting(valueString, defvalue))                               // Try to convert the string to a value
236            this->resetConfigFileEntry();                                           // The conversion failed
237    }
238
239    /**
240        @brief Constructor: Converts the default-value to a string, checks the config-file for a changed value, sets the intern value variable.
241        @param value This is only needed to determine the right type.
242        @param classname The name of the class the variable belongs to
243        @param varname The name of the variable
244        @param defvalue The default-value
245    */
246    ConfigValueContainer::ConfigValueContainer(const std::string& classname, const std::string& varname, const char* defvalue)
247    {
248        this->bAddedDescription_ = false;
249        this->classname_ = classname;
250        this->varname_ = varname;
251        this->type_ = VT_ConstChar;
252
253        this->defvalueString_ = "\"" + std::string(defvalue) + "\"";                // Convert the string to a "config-file-string" with quotes
254        this->searchConfigFileLine();                                               // Search the entry in the config-file
255        std::string valueString = this->parseValueString(false);                    // Parses the value string from the config-file-entry
256        if (!this->parseSting(valueString, defvalue))                               // Try to convert the string to a value
257            this->resetConfigFileEntry();                                           // The conversion failed
258    }
259
260    /**
261        @brief Constructor: Converts the default-value to a string, checks the config-file for a changed value, sets the intern value variable.
262        @param value This is only needed to determine the right type.
263        @param classname The name of the class the variable belongs to
264        @param varname The name of the variable
265        @param defvalue The default-value
266    */
267    ConfigValueContainer::ConfigValueContainer(const std::string& classname, const std::string& varname, Vector2 defvalue)
268    {
269        this->bAddedDescription_ = false;
270        this->classname_ = classname;
271        this->varname_ = varname;
272        this->type_ = VT_Vector2;
273
274        // Try to convert the default-value from Vector2 to string
275        std::ostringstream ostream;
276        if (ostream << "(" << defvalue.x << "," << defvalue.y << ")")
277            this->defvalueString_ = ostream.str();
278        else
279            this->defvalueString_ = "(0,0)";
280
281        this->searchConfigFileLine();                                               // Search the entry in the config-file
282        std::string valueString = this->parseValueString();                         // Parses the value string from the config-file-entry
283        if (!this->parseSting(valueString, defvalue))                               // Try to convert the string to a value
284            this->resetConfigFileEntry();                                           // The conversion failed
285    }
286
287    /**
288        @brief Constructor: Converts the default-value to a string, checks the config-file for a changed value, sets the intern value variable.
289        @param value This is only needed to determine the right type.
290        @param classname The name of the class the variable belongs to
291        @param varname The name of the variable
292        @param defvalue The default-value
293    */
294    ConfigValueContainer::ConfigValueContainer(const std::string& classname, const std::string& varname, Vector3 defvalue)
295    {
296        this->bAddedDescription_ = false;
297        this->classname_ = classname;
298        this->varname_ = varname;
299        this->type_ = VT_Vector3;
300
301        // Try to convert the default-value from Vector3 to string
302        std::ostringstream ostream;
303        if (ostream << "(" << defvalue.x << "," << defvalue.y << "," << defvalue.z << ")")
304            this->defvalueString_ = ostream.str();
305        else
306            this->defvalueString_ = "(0,0,0)";
307
308        this->searchConfigFileLine();                                               // Search the entry in the config-file
309        std::string valueString = this->parseValueString();                         // Parses the value string from the config-file-entry
310        if (!this->parseSting(valueString, defvalue))                               // Try to convert the string to a value
311            this->resetConfigFileEntry();                                           // The conversion failed
312    }
313
314    /**
315        @brief Constructor: Converts the default-value to a string, checks the config-file for a changed value, sets the intern value variable.
316        @param value This is only needed to determine the right type.
317        @param classname The name of the class the variable belongs to
318        @param varname The name of the variable
319        @param defvalue The default-value
320    */
321    ConfigValueContainer::ConfigValueContainer(const std::string& classname, const std::string& varname, ColourValue defvalue)
322    {
323        this->bAddedDescription_ = false;
324        this->classname_ = classname;
325        this->varname_ = varname;
326        this->type_ = VT_ColourValue;
327
328        // Try to convert the default-value from ColourValue to string
329        std::ostringstream ostream;
330        if (ostream << "(" << defvalue.r << "," << defvalue.g << "," << defvalue.b << "," << defvalue.a << ")")
331            this->defvalueString_ = ostream.str();
332        else
333            this->defvalueString_ = "(0,0,0,0)";
334
335        this->searchConfigFileLine();                                               // Search the entry in the config-file
336        std::string valueString = this->parseValueString();                         // Parses the value string from the config-file-entry
337        if (!this->parseSting(valueString, defvalue))                               // Try to convert the string to a value
338            this->resetConfigFileEntry();                                           // The conversion failed
339    }
340
341    /**
342        @brief Parses a given std::string into a value of the type of the associated variable and assigns it.
343        @param input The string to convert
344        @return True if the string was successfully parsed
345    */
346    bool ConfigValueContainer::parseSting(const std::string& input)
347    {
348        if (this->type_ == ConfigValueContainer::VT_Int)
349            return this->parseSting(input, this->value_.value_int_);
350        else if (this->type_ == ConfigValueContainer::VT_uInt)
351            return this->parseSting(input, this->value_.value_uint_);
352        else if (this->type_ == ConfigValueContainer::VT_Char)
353            return this->parseSting(input, this->value_.value_char_);
354        else if (this->type_ == ConfigValueContainer::VT_uChar)
355            return this->parseSting(input, this->value_.value_uchar_);
356        else if (this->type_ == ConfigValueContainer::VT_Float)
357            return this->parseSting(input, this->value_.value_float_);
358        else if (this->type_ == ConfigValueContainer::VT_Double)
359            return this->parseSting(input, this->value_.value_double_);
360        else if (this->type_ == ConfigValueContainer::VT_LongDouble)
361            return this->parseSting(input, this->value_.value_long_double_);
362        else if (this->type_ == ConfigValueContainer::VT_Bool)
363            return this->parseSting(input, this->value_.value_bool_);
364        else if (this->type_ == ConfigValueContainer::VT_String)
365            return this->parseSting(input, this->value_string_);
366        else if (this->type_ == ConfigValueContainer::VT_ConstChar)
367            return this->parseSting(input, this->value_string_);
368        else if (this->type_ == ConfigValueContainer::VT_Vector2)
369            return this->parseSting(input, this->value_vector2_);
370        else if (this->type_ == ConfigValueContainer::VT_Vector3)
371            return this->parseSting(input, this->value_vector3_);
372        else if (this->type_ == ConfigValueContainer::VT_ColourValue)
373            return this->parseSting(input, this->value_colourvalue_);
374
375        return false;
376    }
377
378    /**
379        @brief Parses a given std::string into a value of the type int and assigns it to the right variable. If the conversion failed, the default-value gets assigned.
380        @param input The string to convert
381        @param defvalue The default-value
382        @return True if the string was successfully parsed
383    */
384    bool ConfigValueContainer::parseSting(const std::string& input, int defvalue)
385    {
386        return ConvertValue(&this->value_.value_int_, input, defvalue);
387    }
388
389    /**
390        @brief Parses a given std::string into a value of the type unsigned int and assigns it to the right variable. If the conversion failed, the default-value gets assigned.
391        @param input The string to convert
392        @param defvalue The default-value
393        @return True if the string was successfully parsed
394    */
395    bool ConfigValueContainer::parseSting(const std::string& input, unsigned int defvalue)
396    {
397        return ConvertValue(&this->value_.value_uint_, input, defvalue);
398    }
399
400    /**
401        @brief Parses a given std::string into a value of the type char and assigns it to the right variable. If the conversion failed, the default-value gets assigned.
402        @param input The string to convert
403        @param defvalue The default-value
404        @return True if the string was successfully parsed
405    */
406    bool ConfigValueContainer::parseSting(const std::string& input, char defvalue)
407    {
408        // I used value_int_ instead of value_char_ to avoid number <-> char confusion in the config-file
409        return ConvertValue(&this->value_.value_int_, input, (int)defvalue);
410    }
411
412    /**
413        @brief Parses a given std::string into a value of the type unsigned char and assigns it to the right variable. If the conversion failed, the default-value gets assigned.
414        @param input The string to convert
415        @param defvalue The default-value
416        @return True if the string was successfully parsed
417    */
418    bool ConfigValueContainer::parseSting(const std::string& input, unsigned char defvalue)
419    {
420        // I used value_uint_ instead of value_uchar_ to avoid number <-> char confusion in the config-file
421        return ConvertValue(&this->value_.value_uint_, input, (unsigned int)defvalue);
422    }
423
424    /**
425        @brief Parses a given std::string into a value of the type float and assigns it to the right variable. If the conversion failed, the default-value gets assigned.
426        @param input The string to convert
427        @param defvalue The default-value
428        @return True if the string was successfully parsed
429    */
430    bool ConfigValueContainer::parseSting(const std::string& input, float defvalue)
431    {
432        return ConvertValue(&this->value_.value_float_, input, defvalue);
433    }
434
435    /**
436        @brief Parses a given std::string into a value of the type double and assigns it to the right variable. If the conversion failed, the default-value gets assigned.
437        @param input The string to convert
438        @param defvalue The default-value
439        @return True if the string was successfully parsed
440    */
441    bool ConfigValueContainer::parseSting(const std::string& input, double defvalue)
442    {
443        return ConvertValue(&this->value_.value_double_, input, defvalue);
444    }
445
446    /**
447        @brief Parses a given std::string into a value of the type long double and assigns it to the right variable. If the conversion failed, the default-value gets assigned.
448        @param input The string to convert
449        @param defvalue The default-value
450        @return True if the string was successfully parsed
451    */
452    bool ConfigValueContainer::parseSting(const std::string& input, long double defvalue)
453    {
454        return ConvertValue(&this->value_.value_long_double_, input, defvalue);
455    }
456
457    /**
458        @brief Parses a given std::string into a value of the type bool and assigns it to the right variable. If the conversion failed, the default-value gets assigned.
459        @param input The string to convert
460        @param defvalue The default-value
461        @return True if the string was successfully parsed
462    */
463    bool ConfigValueContainer::parseSting(const std::string& input, bool defvalue)
464    {
465        // Try to parse the value-string - is it a word?
466        if (input.find("true") < input.size()
467         || input.find("True") < input.size()
468         || input.find("yes") < input.size()
469         || input.find("Yes") < input.size())
470            this->value_.value_bool_ = true;
471        else if (input.find("false") < input.size()
472              || input.find("False") < input.size()
473              || input.find("no") < input.size()
474              || input.find("No") < input.size())
475            this->value_.value_bool_ = false;
476        else
477        {
478            // Its not a known word - is it a number?
479            return ConvertValue(&this->value_.value_bool_, input, defvalue);
480        }
481
482        return true;
483    }
484
485    /**
486        @brief Parses a given std::string into a value of the type std::string and assigns it to the right variable. If the conversion failed, the default-value gets assigned.
487        @param input The string to convert
488        @param defvalue The default-value
489        @return True if the string was successfully parsed
490    */
491    bool ConfigValueContainer::parseSting(const std::string& input, const std::string& defvalue)
492    {
493        // Strip the quotes
494        unsigned int pos1 = input.find("\"") + 1;
495        unsigned int pos2 = input.find("\"", pos1);
496
497        // Check if the entry was correctly quoted
498        if (pos1 < input.length() && pos2 < input.length() && !(input.find("\"", pos2 + 1) < input.length()))
499        {
500            // It was - get the string between the quotes
501            this->value_string_ = input.substr(pos1, pos2 - pos1);
502            return true;
503        }
504
505        // It wasn't - use the default-value and restore the entry in the config-file.
506        this->value_string_ = defvalue;
507        return false;
508    }
509
510    /**
511        @brief Parses a given std::string into a value of the type const char* and assigns it to the right variable. If the conversion failed, the default-value gets assigned.
512        @param input The string to convert
513        @param defvalue The default-value
514        @return True if the string was successfully parsed
515    */
516    bool ConfigValueContainer::parseSting(const std::string& input, const char* defvalue)
517    {
518        // Strip the quotes
519        unsigned int pos1 = input.find("\"") + 1;
520        unsigned int pos2 = input.find("\"", pos1);
521
522        // Check if the entry was correctly quoted
523        if (pos1 < input.length() && pos2 < input.length() && !(input.find("\"", pos2 + 1) < input.length()))
524        {
525            // It was - get the string between the quotes
526            this->value_string_ = input.substr(pos1, pos2 - pos1);
527            return true;
528        }
529
530        // It wasn't - use the default-value and restore the entry in the config-file.
531        this->value_string_ = defvalue;
532        return false;
533    }
534
535    /**
536        @brief Parses a given std::string into a value of the type _Vector2 and assigns it to the right variable. If the conversion failed, the default-value gets assigned.
537        @param input The string to convert
538        @param defvalue The default-value
539        @return True if the string was successfully parsed
540    */
541    bool ConfigValueContainer::parseSting(const std::string& input, const Vector2& defvalue)
542    {
543        // Strip the value-string
544        unsigned int pos1 = input.find("(") + 1;
545        unsigned int pos2 = input.find(")", pos1);
546
547        // Try to convert the stripped value-string to Vector2
548        if (pos1 < input.length() && pos2 < input.length() && pos1 < pos2)
549        {
550            std::vector<std::string> tokens = tokenize(input.substr(pos1, pos2 - pos1), ",");
551            if (!ConvertValue(&this->value_vector2_.x, tokens[0]))
552            {
553                this->value_vector2_ = defvalue;
554                return false;
555            }
556            if (!ConvertValue(&this->value_vector2_.y, tokens[1]))
557            {
558                this->value_vector2_ = defvalue;
559                return false;
560            }
561
562            return true;
563        }
564
565        this->value_vector2_ = defvalue;
566        return false;
567    }
568
569    /**
570        @brief Parses a given std::string into a value of the type Vector3 and assigns it to the right variable. If the conversion failed, the default-value gets assigned.
571        @param input The string to convert
572        @param defvalue The default-value
573        @return True if the string was successfully parsed
574    */
575    bool ConfigValueContainer::parseSting(const std::string& input, const Vector3& defvalue)
576    {
577        // Strip the value-string
578        unsigned int pos1 = input.find("(") + 1;
579        unsigned int pos2 = input.find(")", pos1);
580
581        // Try to convert the stripped value-string to Vector3
582        if (pos1 < input.length() && pos2 < input.length() && pos1 < pos2)
583        {
584            std::vector<std::string> tokens = tokenize(input.substr(pos1, pos2 - pos1), ",");
585            if (!ConvertValue(&this->value_vector3_.x, tokens[0]))
586            {
587                this->value_vector3_ = defvalue;
588                return false;
589            }
590            if (!ConvertValue(&this->value_vector3_.y, tokens[1]))
591            {
592                this->value_vector3_ = defvalue;
593                return false;
594            }
595            if (!ConvertValue(&this->value_vector3_.z, tokens[2]))
596            {
597                this->value_vector3_ = defvalue;
598                return false;
599            }
600
601            return true;
602        }
603
604        this->value_vector3_ = defvalue;
605        return false;
606    }
607
608    /**
609        @brief Parses a given std::string into a value of the type ColourValue and assigns it to the right variable. If the conversion failed, the default-value gets assigned.
610        @param input The string to convert
611        @param defvalue The default-value
612        @return True if the string was successfully parsed
613    */
614    bool ConfigValueContainer::parseSting(const std::string& input, const ColourValue& defvalue)
615    {
616        // Strip the value-string
617        unsigned int pos1 = input.find("(") + 1;
618        unsigned int pos2 = input.find(")", pos1);
619
620        // Try to convert the stripped value-string to Vector3
621        if (pos1 < input.length() && pos2 < input.length() && pos1 < pos2)
622        {
623            std::vector<std::string> tokens = tokenize(input.substr(pos1, pos2 - pos1), ",");
624            if (!ConvertValue(&this->value_colourvalue_.r, tokens[0]))
625            {
626                this->value_colourvalue_ = defvalue;
627                return false;
628            }
629            if (!ConvertValue(&this->value_colourvalue_.g, tokens[1]))
630            {
631                this->value_colourvalue_ = defvalue;
632                return false;
633            }
634            if (!ConvertValue(&this->value_colourvalue_.b, tokens[2]))
635            {
636                this->value_colourvalue_ = defvalue;
637                return false;
638            }
639            if (!ConvertValue(&this->value_colourvalue_.a, tokens[3]))
640            {
641                this->value_colourvalue_ = defvalue;
642                return false;
643            }
644
645            return true;
646        }
647
648        this->value_colourvalue_ = defvalue;
649        return false;
650    }
651
652    /**
653        @brief Sets the corresponding entry in the config-file back to the default value.
654    */
655    void ConfigValueContainer::resetConfigFileEntry()
656    {
657        (*this->configFileLine_) = this->varname_ + "=" + this->defvalueString_;
658        ConfigValueContainer::writeConfigFile(CONFIGFILEPATH);
659    }
660
661    /**
662        @brief Sets the value of the variable back to the default value and resets the config-file entry.
663    */
664    void ConfigValueContainer::resetConfigValue()
665    {
666        this->parseSting(this->defvalueString_);
667        this->resetConfigFileEntry();
668    }
669
670    /**
671        @brief Searches the corresponding entry in the config-file and creates it, if there is no entry.
672    */
673    void ConfigValueContainer::searchConfigFileLine()
674    {
675        // Read the file if needed
676        if (!ConfigValueContainer::finishedReadingConfigFile())
677            ConfigValueContainer::readConfigFile(CONFIGFILEPATH);
678
679        // The string of the section we're searching
680        std::string section = "";
681        section.append("[");
682        section.append(this->classname_);
683        section.append("]");
684
685        // Iterate through all config-file-lines
686        bool success = false;
687        std::list<std::string>::iterator it1;
688        for(it1 = ConfigValueContainer::getConfigFileLines().begin(); it1 != ConfigValueContainer::getConfigFileLines().end(); ++it1)
689        {
690            // Don't try to parse comments
691            if (this->isComment(*it1))
692                continue;
693
694            if ((*it1).find(section) < (*it1).length())
695            {
696                // We found the right section
697                bool bLineIsEmpty = false;
698                std::list<std::string>::iterator positionToPutNewLineAt;
699
700                // Iterate through all lines in the section
701                std::list<std::string>::iterator it2;
702                for(it2 = ++it1; it2 != ConfigValueContainer::getConfigFileLines().end(); ++it2)
703                {
704                    // Don't try to parse comments
705                    if (this->isComment(*it2))
706                        continue;
707
708                    // This if-else block is used to write a new line right after the last line of the
709                    // section but in front of the following empty lines before the next section.
710                    // (So this helps to keep a nice formatting with empty-lines between sections in the config-file)
711                    if (this->isEmpty(*it2))
712                    {
713                        if (!bLineIsEmpty)
714                        {
715                            bLineIsEmpty = true;
716                            positionToPutNewLineAt = it2;
717                        }
718                    }
719                    else
720                    {
721                        if (!bLineIsEmpty)
722                            positionToPutNewLineAt = it2;
723
724                        bLineIsEmpty = false;
725                    }
726
727                    // Look out for the beginning of the next section
728                    unsigned int open = (*it2).find("[");
729                    unsigned int close = (*it2).find("]");
730                    if ((open < (*it2).length()) && (close < (*it2).length()) && (open < close))
731                    {
732                        // The next section startet, so our line isn't yet in the file - now we add it and safe the file
733                        this->configFileLine_ = this->getConfigFileLines().insert(positionToPutNewLineAt, this->varname_ + "=" + this->defvalueString_);
734                        ConfigValueContainer::writeConfigFile(CONFIGFILEPATH);
735                        success = true;
736                        break;
737                    }
738
739                    // Look out for the variable-name
740                    if ((*it2).find(this->varname_) < (*it2).length())
741                    {
742                        // We found the right line - safe it and return
743                        this->configFileLine_ = it2;
744                        success = true;
745                        break;
746                    }
747                }
748
749                // Check if we succeeded
750                if (!success)
751                {
752                    // Looks like we found the right section, but the file ended without containing our variable - so we add it and safe the file
753                    this->configFileLine_ = this->getConfigFileLines().insert(positionToPutNewLineAt, this->varname_ + "=" + this->defvalueString_);
754                    ConfigValueContainer::writeConfigFile(CONFIGFILEPATH);
755                    success = true;
756                }
757                break;
758            }
759        }
760
761        // Check if we succeeded
762        if (!success)
763        {
764            // We obviously didn't found the right section, so we'll create it
765            this->getConfigFileLines().push_back("[" + this->classname_ + "]");                   // Create the section
766            this->getConfigFileLines().push_back(this->varname_ + "=" + this->defvalueString_);   // Create the line
767            this->configFileLine_ = --this->getConfigFileLines().end();                           // Set the pointer to the last element
768            success = true;
769            this->getConfigFileLines().push_back("");                                             // Add an empty line - this is needed for the algorithm in the searchConfigFileLine-function
770            ConfigValueContainer::writeConfigFile(CONFIGFILEPATH);                              // Save the changed config-file
771        }
772    }
773
774    /**
775        @brief Determines if a line in the config-file is a comment.
776        @param line The line to check
777        @return True = it's a comment
778    */
779    bool ConfigValueContainer::isComment(const std::string& line)
780    {
781        // Strip the line, whitespaces are disturbing
782        std::string teststring = getStrippedLine(line);
783
784        // There are four possible comment-symbols:
785        //  1) #comment in script-language style
786        //  2) %comment in matlab style
787        //  3) ;comment in unreal tournament config-file style
788        //  4) //comment in code style
789        if (teststring[0] == '#' || teststring[0] == '%' || teststring[0] == ';' || (teststring[0] == '/' && teststring[0] == '/'))
790            return true;
791
792        return false;
793    }
794
795    /**
796        @brief Determines if a line in the config-file is empty (contains only whitespaces).
797        @param line The line to check
798        @return True = it's empty
799    */
800    bool ConfigValueContainer::isEmpty(const std::string& line)
801    {
802        return getStrippedLine(line) == "";
803    }
804
805    /**
806        @brief Removes all whitespaces from a line.
807        @param line The line to strip
808        @return The stripped line
809    */
810    std::string ConfigValueContainer::getStrippedLine(const std::string& line)
811    {
812        std::string output = line;
813        unsigned int pos;
814        while ((pos = output.find(" ")) < output.length())
815            output.erase(pos, 1);
816        while ((pos = output.find("\t")) < output.length())
817            output.erase(pos, 1);
818
819        return output;
820    }
821
822    /**
823        @brief Returns the part in the corresponding config-file-entry of the container that defines the value.
824        @param bStripped True = strip the value-string
825        @return The value-string
826    */
827    std::string ConfigValueContainer::parseValueString(bool bStripped)
828    {
829        std::string output;
830        if (bStripped)
831            output = this->getStrippedLine(*this->configFileLine_);
832        else
833            output = *this->configFileLine_;
834
835        return output.substr(output.find("=") + 1);
836    }
837
838    /**
839        @returns a list, containing all entrys in the config-file.
840    */
841    std::list<std::string>& ConfigValueContainer::getConfigFileLines()
842    {
843        // This is done to avoid problems while executing this code before main()
844        static std::list<std::string> configFileLinesStaticReference = std::list<std::string>();
845        return configFileLinesStaticReference;
846    }
847
848    /**
849        @brief Returns true if the ConfigFile is read and stored into the ConfigFile-lines-list.
850        @param finished This is used to change the state
851        @return True if the ConfigFile is read and stored into the ConfigFile-lines-list
852    */
853    bool ConfigValueContainer::finishedReadingConfigFile(bool finished)
854    {
855        // This is done to avoid problems while executing this code before main()
856        static bool finishedReadingConfigFileStaticVariable = false;
857
858        if (finished)
859            finishedReadingConfigFileStaticVariable = true;
860
861        return finishedReadingConfigFileStaticVariable;
862    }
863
864    /**
865        @brief Reads the config-file and stores the lines in a list.
866        @param filename The name of the config-file
867    */
868    void ConfigValueContainer::readConfigFile(const std::string& filename)
869    {
870        // This creates the file if it's not existing
871        std::ofstream createFile;
872        createFile.open(filename.c_str(), std::fstream::app);
873        createFile.close();
874
875        // Open the file
876        std::ifstream file;
877        file.open(filename.c_str(), std::fstream::in);
878
879        if (!file.is_open())
880        {
881            COUT(1) << "Error: Couldn't open config-file " << filename << " to read the config values!" << std::endl;
882            return;
883        }
884
885        char line[1024];
886
887        // Iterate through the file and add the lines into the list
888        while (file.good() && !file.eof())
889        {
890            file.getline(line, 1024);
891            ConfigValueContainer::getConfigFileLines().push_back(line);
892//            std::cout << "### ->" << line << "<- : empty: " << isEmpty(line) << " comment: " << isComment(line) << std::endl;
893        }
894
895        // The last line is useless
896        ConfigValueContainer::getConfigFileLines().pop_back();
897
898        // Add an empty line to the end of the file if needed
899        // this is needed for the algorithm in the searchConfigFileLine-function
900        if ((ConfigValueContainer::getConfigFileLines().size() > 0) && !isEmpty(*ConfigValueContainer::getConfigFileLines().rbegin()))
901        {
902//            std::cout << "### newline added" << std::endl;
903            ConfigValueContainer::getConfigFileLines().push_back("");
904        }
905
906        file.close();
907
908        ConfigValueContainer::finishedReadingConfigFile(true);
909    }
910
911    /**
912        @brief Writes the content of the list, containing all lines of the config-file, into the config-file.
913        @param filename The name of the config-file
914    */
915    void ConfigValueContainer::writeConfigFile(const std::string& filename)
916    {
917        // Make sure we stored the config-file in the list
918        if (!ConfigValueContainer::finishedReadingConfigFile())
919            ConfigValueContainer::readConfigFile(filename);
920
921        // Open the file
922        std::ofstream file;
923        file.open(filename.c_str(), std::fstream::out);
924
925        if (!file.is_open())
926        {
927            COUT(1) << "Error: Couldn't open config-file " << filename << " to write the config values!" << std::endl;
928            return;
929        }
930
931        // Iterate through the list an write the lines into the file
932        std::list<std::string>::iterator it;
933        for (it = ConfigValueContainer::getConfigFileLines().begin(); it != ConfigValueContainer::getConfigFileLines().end(); ++it)
934        {
935            file << (*it) << std::endl;
936        }
937
938        file.close();
939    }
940
941    /**
942        @brief Adds a description to the config-value.
943        @param description The description
944    */
945    void ConfigValueContainer::description(const std::string& description)
946    {
947        if (!this->bAddedDescription_)
948        {
949            this->description_ = std::string("ConfigValueDescription::" + this->classname_ + "::" + this->varname_);
950            Language::getLanguage().addEntry(this->description_, description);
951            this->bAddedDescription_ = true;
952        }
953    }
954}
Note: See TracBrowser for help on using the repository browser.