Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

intern changes in the ConfigValueContainer

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