Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/core3/src/core/ConfigValueContainer.cc @ 1610

Last change on this file since 1610 was 1610, checked in by landauf, 16 years ago
  • fixed bug #1 in ConfigValueContainer (callback not being called the first time)
  • fixed another bug in XMLPort, caused by the recently added support for extern types
  • Property svn:eol-style set to native
File size: 13.2 KB
Line 
1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *                    > www.orxonox.net <
4 *
5 *
6 *   License notice:
7 *
8 *   This program is free software; you can redistribute it and/or
9 *   modify it under the terms of the GNU General Public License
10 *   as published by the Free Software Foundation; either version 2
11 *   of the License, or (at your option) any later version.
12 *
13 *   This program is distributed in the hope that it will be useful,
14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 *   GNU General Public License for more details.
17 *
18 *   You should have received a copy of the GNU General Public License
19 *   along with this program; if not, write to the Free Software
20 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 *
22 *   Author:
23 *      Fabian 'x3n' Landau
24 *   Co-authors:
25 *      ...
26 *
27 */
28
29/**
30    @file ConfigValueContainer.cc
31    @brief Implementation of the ConfigValueContainer class.
32*/
33
34#include "ConfigValueContainer.h"
35
36#include <fstream>
37
38#include "util/SubString.h"
39#include "util/Convert.h"
40#include "Language.h"
41#include "Identifier.h"
42
43#define MAX_VECTOR_INDEX 255 // to avoid up to 4*10^9 vector entries in the config file after accidentally using a wrong argument
44
45
46namespace orxonox
47{
48    /**
49        @brief Constructor: Converts the default-value to a string, checks the config-file for a changed value, sets the intern value variable.
50        @param type The type of the corresponding config-file
51        @param identifier The identifier of the class the variable belongs to
52        @param varname The name of the variable
53        @param defvalue The default-value
54    */
55    ConfigValueContainer::ConfigValueContainer(ConfigFileType type, Identifier* identifier, const std::string& varname, const MultiTypeMath& defvalue)
56    {
57        this->type_ = type;
58        this->identifier_ = identifier;
59        this->sectionname_ = identifier->getName();
60        this->varname_ = varname;
61        this->callback_ = 0;
62        this->bContainerIsNew_ = true;
63        this->bDoInitialCallback_ = false;
64        this->bAddedDescription_ = false;
65
66        this->value_ = defvalue;
67        this->bIsVector_ = false;
68
69        this->defvalueString_ = defvalue.toString();
70        this->update();
71    }
72
73    /**
74        @brief Constructor: Converts the default-value to a string, checks the config-file for a changed value, sets the intern value variable.
75        @param type The type of the corresponding config-file
76        @param identifier The identifier of the class the variable belongs to
77        @param varname The name of the variable
78        @param defvalue The default-value
79    */
80    ConfigValueContainer::ConfigValueContainer(ConfigFileType type, Identifier* identifier, const std::string& varname, const std::vector<MultiTypeMath>& defvalue)
81    {
82        this->type_ = type;
83        this->identifier_ = identifier;
84        this->sectionname_ = identifier->getName();
85        this->varname_ = varname;
86        this->callback_ = 0;
87        this->bContainerIsNew_ = true;
88        this->bDoInitialCallback_ = false;
89        this->bAddedDescription_ = false;
90
91        this->valueVector_ = defvalue;
92        this->bIsVector_ = true;
93
94        if (defvalue.size() > 0)
95        {
96                this->value_ = defvalue[0];
97
98            for (unsigned int i = 0; i < defvalue.size(); i++)
99            {
100                ConfigFileManager::getSingleton()->getValue(this->type_, this->sectionname_, this->varname_, i, defvalue[i].toString(), this->value_.isA(MT_string));
101                this->defvalueStringVector_.push_back(defvalue[i].toString());
102            }
103
104            this->update();
105        }
106    }
107
108    /**
109        @brief Destructor: Deletes the callback object if necessary.
110    */
111    ConfigValueContainer::~ConfigValueContainer()
112    {
113        if (this->callback_)
114            delete this->callback_;
115    }
116
117    /**
118        @brief Assigns a new value to the config-value of all objects and writes the change into the config-file.
119        @param input The new value
120        @return True if the new value was successfully assigned
121    */
122    bool ConfigValueContainer::set(const MultiTypeMath& input)
123    {
124        if (this->bIsVector_)
125        {
126            return this->callFunctionWithIndex(&ConfigValueContainer::set, input.toString());
127        }
128        else
129        {
130            if (this->tset(input))
131            {
132                ConfigFileManager::getSingleton()->setValue(this->type_, this->sectionname_, this->varname_, input.toString(), this->value_.isA(MT_string));
133                return true;
134            }
135        }
136        return false;
137    }
138
139    /**
140        @brief Assigns a new value to the config-value of all objects and writes the change into the config-file.
141        @param index The index in the vector
142        @param input The new value
143        @return True if the new value was successfully assigned
144    */
145    bool ConfigValueContainer::set(unsigned int index, const MultiTypeMath& input)
146    {
147        if (this->bIsVector_)
148        {
149            if (this->tset(index, input))
150            {
151                ConfigFileManager::getSingleton()->setValue(this->type_, this->sectionname_, this->varname_, index, input.toString(), this->value_.isA(MT_string));
152                return true;
153            }
154        }
155        else
156        {
157            COUT(1) << "Error: Config-value '" << this->varname_ << "' in " << this->sectionname_ << " is not a vector." << std::endl;
158        }
159        return false;
160    }
161
162    /**
163        @brief Assigns a new value to the config-value of all objects, but doesn't change the config-file (t stands for temporary).
164        @param input The new value. If bIsVector_ then write "index value"
165        @return True if the new value was successfully assigned
166    */
167    bool ConfigValueContainer::tset(const MultiTypeMath& input)
168    {
169        if (this->bIsVector_)
170        {
171            return this->callFunctionWithIndex(&ConfigValueContainer::tset, input.toString());
172        }
173        else
174        {
175            MultiTypeMath temp = this->value_;
176            if (temp.assimilate(input))
177            {
178                this->value_ = temp;
179                if (this->identifier_)
180                    this->identifier_->updateConfigValues();
181
182                return true;
183            }
184        }
185        return false;
186    }
187
188    /**
189        @brief Assigns a new value to the config-value of all objects, but doesn't change the config-file (t stands for temporary).
190        @param index The index in the vector
191        @param input The new value
192        @return True if the new value was successfully assigned
193    */
194    bool ConfigValueContainer::tset(unsigned int index, const MultiTypeMath& input)
195    {
196        if (this->bIsVector_)
197        {
198            if (index > MAX_VECTOR_INDEX)
199            {
200                COUT(1) << "Error: Index " << index << " is too large." << std::endl;
201                return false;
202            }
203
204            if (index >= this->valueVector_.size())
205            {
206                for (unsigned int i = this->valueVector_.size(); i <= index; i++)
207                {
208                    this->valueVector_.push_back(MultiTypeMath());
209                }
210            }
211
212            MultiTypeMath temp = this->value_;
213            if (temp.assimilate(input))
214            {
215                this->valueVector_[index] = temp;
216
217                if (this->identifier_)
218                    this->identifier_->updateConfigValues();
219
220                return true;
221            }
222        }
223        else
224        {
225            COUT(1) << "Error: Config-value '" << this->varname_ << "' in " << this->sectionname_ << " is not a vector." << std::endl;
226        }
227        return false;
228    }
229
230    /**
231        @brief Adds a new entry to the end of the vector.
232        @param input The new entry
233        @return True if the new entry was successfully added
234    */
235    bool ConfigValueContainer::add(const MultiTypeMath& input)
236    {
237        if (this->bIsVector_)
238            return this->set(this->valueVector_.size(), input);
239
240        COUT(1) << "Error: Config-value '" << this->varname_ << "' in " << this->sectionname_ << " is not a vector." << std::endl;
241        return false;
242    }
243
244    /**
245        @brief Removes an existing entry from the vector.
246        @param index The index of the entry
247        @return True if the entry was removed
248    */
249    bool ConfigValueContainer::remove(unsigned int index)
250    {
251        if (this->bIsVector_)
252        {
253            if (index < this->valueVector_.size())
254            {
255                // Erase the entry from the vector, change (shift) all entries beginning with index in the config file, remove the last entry from the file
256                this->valueVector_.erase(this->valueVector_.begin() + index);
257                for (unsigned int i = index; i < this->valueVector_.size(); i++)
258                    ConfigFileManager::getSingleton()->setValue(this->type_, this->sectionname_, this->varname_, i, this->valueVector_[i], this->value_.isA(MT_string));
259                ConfigFileManager::getSingleton()->deleteVectorEntries(this->type_, this->sectionname_, this->varname_, this->valueVector_.size());
260
261                return true;
262            }
263            COUT(1) << "Error: Invalid vector-index." << std::endl;
264        }
265
266        COUT(1) << "Error: Config-value '" << this->varname_ << "' in " << this->sectionname_ << " is not a vector." << std::endl;
267        return false;
268    }
269
270    /**
271        @brief Sets the value of the variable back to the default value and resets the config-file entry.
272    */
273    bool ConfigValueContainer::reset()
274    {
275        if (!this->bIsVector_)
276            return this->set(this->defvalueString_);
277        else
278        {
279            bool success = true;
280            for (unsigned int i = 0; i < this->defvalueStringVector_.size(); i++)
281                if (!this->set(i, this->defvalueStringVector_[i]))
282                    success = false;
283            ConfigFileManager::getSingleton()->deleteVectorEntries(this->type_, this->sectionname_, this->varname_, this->defvalueStringVector_.size());
284            return success;
285        }
286    }
287
288    /**
289        @brief Retrieves the configured value from the currently loaded config-file.
290    */
291    void ConfigValueContainer::update()
292    {
293        if (!this->bIsVector_)
294            this->value_.fromString(ConfigFileManager::getSingleton()->getValue(this->type_, this->sectionname_, this->varname_, this->defvalueString_, this->value_.isA(MT_string)));
295        else
296        {
297            this->valueVector_.clear();
298            for (unsigned int i = 0; i < ConfigFileManager::getSingleton()->getVectorSize(this->type_, this->sectionname_, this->varname_); i++)
299            {
300                if (i < this->defvalueStringVector_.size())
301                {
302                    this->value_.fromString(ConfigFileManager::getSingleton()->getValue(this->type_, this->sectionname_, this->varname_, i, this->defvalueStringVector_[i], this->value_.isA(MT_string)));
303                }
304                else
305                {
306                    this->value_.fromString(ConfigFileManager::getSingleton()->getValue(this->type_, this->sectionname_, this->varname_, i, MultiTypeMath(), this->value_.isA(MT_string)));
307                }
308
309                this->valueVector_.push_back(this->value_);
310            }
311        }
312    }
313
314    /**
315        @brief Calls the given function with parsed index and the parsed argument from the input string.
316        @param function The function to call
317        @param input The input string
318        @return The returnvalue of the functioncall
319    */
320    bool ConfigValueContainer::callFunctionWithIndex(bool (ConfigValueContainer::* function) (unsigned int, const MultiTypeMath&), const std::string& input)
321    {
322        SubString token(input, " ", SubString::WhiteSpaces, true, '\\', false, '"', false, '(', ')', false, '\0');
323        int index = -1;
324        bool success = false;
325
326        if (token.size() > 0)
327            success = ConvertValue(&index, token[0]);
328
329        if (!success || index < 0 || index > MAX_VECTOR_INDEX)
330        {
331            if (!success)
332            {
333                COUT(1) << "Error: Config-value '" << this->varname_ << "' in " << this->sectionname_ << " is a vector." << std::endl;
334            }
335            else
336            {
337                COUT(1) << "Error: Invalid vector-index." << std::endl;
338            }
339            return false;
340        }
341
342        if (token.size() >= 2)
343            return (this->*function)(index, token.subSet(1).join());
344        else
345            return (this->*function)(index, "");
346    }
347
348    /**
349        @brief Adds a description to the config-value.
350        @param description The description
351    */
352    ConfigValueContainer& ConfigValueContainer::description(const std::string& description)
353    {
354        if (!this->bAddedDescription_)
355        {
356            this->description_ = std::string("ConfigValueDescription::" + this->identifier_->getName() + "::" + this->varname_);
357            AddLanguageEntry(this->description_, description);
358            this->bAddedDescription_ = true;
359        }
360        return (*this);
361    }
362
363    /**
364        @brief Returns the description of the config-value.
365        @return The description
366    */
367    const std::string& ConfigValueContainer::getDescription() const
368    {
369        return GetLocalisation(this->description_);
370    }
371}
Note: See TracBrowser for help on using the repository browser.