Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

added a new class: Language
it's a manager for different language files to store translations of ingame text (it uses the default text, defined in the code, if no translation in the configured language is available)

File size: 42.9 KB
Line 
1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *
4 *
5 *   License notice:
6 *
7 *   This program is free software; you can redistribute it and/or
8 *   modify it under the terms of the GNU General Public License
9 *   as published by the Free Software Foundation; either version 2
10 *   of the License, or (at your option) any later version.
11 *
12 *   This program is distributed in the hope that it will be useful,
13 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
14 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 *   GNU General Public License for more details.
16 *
17 *   You should have received a copy of the GNU General Public License
18 *   along with this program; if not, write to the Free Software
19 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
20 *
21 *   Author:
22 *      Fabian 'x3n' Landau
23 *   Co-authors:
24 *      ...
25 *
26 */
27
28#include <fstream>
29
30#include "../../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 and resets the config-file entry.
650    */
651    void ConfigValueContainer::resetConfigValue()
652    {
653        this->parseSting(this->defvalueString_);
654        this->resetConfigFileEntry();
655    }
656
657    /**
658        @brief Searches the corresponding entry in the config-file and creates it, if there is no entry.
659    */
660    void ConfigValueContainer::searchConfigFileLine()
661    {
662        // Read the file if needed
663        if (!ConfigValueContainer::finishedReadingConfigFile())
664            ConfigValueContainer::readConfigFile(CONFIGFILEPATH);
665
666        // The string of the section we're searching
667        std::string section = "";
668        section.append("[");
669        section.append(this->classname_);
670        section.append("]");
671
672        // Iterate through all config-file-lines
673        bool success = false;
674        std::list<std::string>::iterator it1;
675        for(it1 = ConfigValueContainer::getConfigFileLines().begin(); it1 != ConfigValueContainer::getConfigFileLines().end(); ++it1)
676        {
677            // Don't try to parse comments
678            if (this->isComment(*it1))
679                continue;
680
681            if ((*it1).find(section) < (*it1).length())
682            {
683                // We found the right section
684                bool bLineIsEmpty = false;
685                std::list<std::string>::iterator positionToPutNewLineAt;
686
687                // Iterate through all lines in the section
688                std::list<std::string>::iterator it2;
689                for(it2 = ++it1; it2 != ConfigValueContainer::getConfigFileLines().end(); ++it2)
690                {
691                    // Don't try to parse comments
692                    if (this->isComment(*it2))
693                        continue;
694
695                    // This if-else block is used to write a new line right after the last line of the
696                    // section but in front of the following empty lines before the next section.
697                    // (So this helps to keep a nice formatting with empty-lines between sections in the config-file)
698                    if (this->isEmpty(*it2))
699                    {
700                        if (!bLineIsEmpty)
701                        {
702                            bLineIsEmpty = true;
703                            positionToPutNewLineAt = it2;
704                        }
705                    }
706                    else
707                    {
708                        if (!bLineIsEmpty)
709                            positionToPutNewLineAt = it2;
710
711                        bLineIsEmpty = false;
712                    }
713
714                    // Look out for the beginning of the next section
715                    unsigned int open = (*it2).find("[");
716                    unsigned int close = (*it2).find("]");
717                    if ((open < (*it2).length()) && (close < (*it2).length()) && (open < close))
718                    {
719                        // The next section startet, so our line isn't yet in the file - now we add it and safe the file
720                        this->configFileLine_ = this->getConfigFileLines().insert(positionToPutNewLineAt, this->varname_ + "=" + this->defvalueString_);
721                        ConfigValueContainer::writeConfigFile(CONFIGFILEPATH);
722                        success = true;
723                        break;
724                    }
725
726                    // Look out for the variable-name
727                    if ((*it2).find(this->varname_) < (*it2).length())
728                    {
729                        // We found the right line - safe it and return
730                        this->configFileLine_ = it2;
731                        success = true;
732                        break;
733                    }
734                }
735
736                // Check if we succeeded
737                if (!success)
738                {
739                    // Looks like we found the right section, but the file ended without containing our variable - so we add it and safe the file
740                    this->configFileLine_ = this->getConfigFileLines().insert(positionToPutNewLineAt, this->varname_ + "=" + this->defvalueString_);
741                    ConfigValueContainer::writeConfigFile(CONFIGFILEPATH);
742                    success = true;
743                }
744                break;
745            }
746        }
747
748        // Check if we succeeded
749        if (!success)
750        {
751            // We obviously didn't found the right section, so we'll create it
752            this->getConfigFileLines().push_back("[" + this->classname_ + "]");                   // Create the section
753            this->getConfigFileLines().push_back(this->varname_ + "=" + this->defvalueString_);   // Create the line
754            this->configFileLine_ = --this->getConfigFileLines().end();                           // Set the pointer to the last element
755            success = true;
756            this->getConfigFileLines().push_back("");                                             // Add an empty line - this is needed for the algorithm in the searchConfigFileLine-function
757            ConfigValueContainer::writeConfigFile(CONFIGFILEPATH);                              // Save the changed config-file
758        }
759    }
760
761    /**
762        @brief Determines if a line in the config-file is a comment.
763        @param line The line to check
764        @return True = it's a comment
765    */
766    bool ConfigValueContainer::isComment(const std::string& line)
767    {
768        // Strip the line, whitespaces are disturbing
769        std::string teststring = getStrippedLine(line);
770
771        // There are four possible comment-symbols:
772        //  1) #comment in script-language style
773        //  2) %comment in matlab style
774        //  3) ;comment in unreal tournament config-file style
775        //  4) //comment in code style
776        if (teststring[0] == '#' || teststring[0] == '%' || teststring[0] == ';' || (teststring[0] == '/' && teststring[0] == '/'))
777            return true;
778
779        return false;
780    }
781
782    /**
783        @brief Determines if a line in the config-file is empty (contains only whitespaces).
784        @param line The line to check
785        @return True = it's empty
786    */
787    bool ConfigValueContainer::isEmpty(const std::string& line)
788    {
789        return getStrippedLine(line) == "";
790    }
791
792    /**
793        @brief Removes all whitespaces from a line.
794        @param line The line to strip
795        @return The stripped line
796    */
797    std::string ConfigValueContainer::getStrippedLine(const std::string& line)
798    {
799        std::string output = line;
800        unsigned int pos;
801        while ((pos = output.find(" ")) < output.length())
802            output.erase(pos, 1);
803        while ((pos = output.find("\t")) < output.length())
804            output.erase(pos, 1);
805
806        return output;
807    }
808
809    /**
810        @brief Returns the part in the corresponding config-file-entry of the container that defines the value.
811        @param bStripped True = strip the value-string
812        @return The value-string
813    */
814    std::string ConfigValueContainer::parseValueString(bool bStripped)
815    {
816        std::string output;
817        if (bStripped)
818            output = this->getStrippedLine(*this->configFileLine_);
819        else
820            output = *this->configFileLine_;
821
822        return output.substr(output.find("=") + 1);
823    }
824
825    /**
826        @returns a list, containing all entrys in the config-file.
827    */
828    std::list<std::string>& ConfigValueContainer::getConfigFileLines()
829    {
830        // This is done to avoid problems while executing this code before main()
831        static std::list<std::string> configFileLinesStaticReference = std::list<std::string>();
832        return configFileLinesStaticReference;
833    }
834
835    /**
836        @brief Returns true if the ConfigFile is read and stored into the ConfigFile-lines-list.
837        @param finished This is used to change the state
838        @return True if the ConfigFile is read and stored into the ConfigFile-lines-list
839    */
840    bool ConfigValueContainer::finishedReadingConfigFile(bool finished)
841    {
842        // This is done to avoid problems while executing this code before main()
843        static bool finishedReadingConfigFileStaticVariable = false;
844
845        if (finished)
846            finishedReadingConfigFileStaticVariable = true;
847
848        return finishedReadingConfigFileStaticVariable;
849    }
850
851    /**
852        @brief Reads the config-file and stores the lines in a list.
853        @param filename The name of the config-file
854    */
855    void ConfigValueContainer::readConfigFile(const std::string& filename)
856    {
857        // This creates the file if it's not existing
858        std::ofstream createFile;
859        createFile.open(filename.c_str(), std::fstream::app);
860        createFile.close();
861
862        // Open the file
863        std::ifstream file;
864        file.open(filename.c_str(), std::fstream::in);
865
866        if (!file.is_open())
867        {
868            COUT(1) << "Error: Couldn't open config-file " << filename << " to read the config values!" << std::endl;
869            return;
870        }
871
872        char line[1024];
873
874        // Iterate through the file and add the lines into the list
875        while (file.good() && !file.eof())
876        {
877            file.getline(line, 1024);
878            ConfigValueContainer::getConfigFileLines().push_back(line);
879//            std::cout << "### ->" << line << "<- : empty: " << isEmpty(line) << " comment: " << isComment(line) << std::endl;
880        }
881
882        // The last line is useless
883        ConfigValueContainer::getConfigFileLines().pop_back();
884
885        // Add an empty line to the end of the file if needed
886        // this is needed for the algorithm in the searchConfigFileLine-function
887        if ((ConfigValueContainer::getConfigFileLines().size() > 0) && !isEmpty(*ConfigValueContainer::getConfigFileLines().rbegin()))
888        {
889//            std::cout << "### newline added" << std::endl;
890            ConfigValueContainer::getConfigFileLines().push_back("");
891        }
892
893        file.close();
894
895        ConfigValueContainer::finishedReadingConfigFile(true);
896    }
897
898    /**
899     *  @param Writes the content of the list, containing all lines of the config-file, into the config-file.
900     *  @param filename The name of the config-file
901     */
902    void ConfigValueContainer::writeConfigFile(const std::string& filename)
903    {
904        // Make sure we stored the config-file in the list
905        if (!ConfigValueContainer::finishedReadingConfigFile())
906            ConfigValueContainer::readConfigFile(filename);
907
908        // Open the file
909        std::ofstream file;
910        file.open(filename.c_str(), std::fstream::out);
911
912        if (!file.is_open())
913        {
914            COUT(1) << "Error: Couldn't open config-file " << filename << " to write the config values!" << std::endl;
915            return;
916        }
917
918        // Iterate through the list an write the lines into the file
919        std::list<std::string>::iterator it;
920        for (it = ConfigValueContainer::getConfigFileLines().begin(); it != ConfigValueContainer::getConfigFileLines().end(); ++it)
921        {
922            file << (*it) << std::endl;
923        }
924
925        file.close();
926    }
927}
Note: See TracBrowser for help on using the repository browser.