Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/FICN/src/orxonox/core/ConfigValueContainer.cc @ 742

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

moved all files from misc and the tinyxml folder into the new util folder

File size: 44.1 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            COUT(4) << "Added description " << this->description_ << std::endl;
953            COUT(4) << "Translation is: " << Language::getLanguage().getTranslation(this->description_) << std::endl;
954        }
955    }
956}
Note: See TracBrowser for help on using the repository browser.