Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 1607 was 1596, checked in by landauf, 16 years ago
  • added feature to add a callback function to configvalues. they get called if the value changes. an examples is in Core.cc.
  • changed the SetConfigValue macro and the Identifier::updateConfigValues() function to work properly with inherited classes in both possible cases: 1) they overwrite the config-value or 2) they don't. an example is ParticleProjectile that defines it's own speed_ configvalue.
  • Property svn:eol-style set to native
File size: 13.0 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
63        this->value_ = defvalue;
64        this->bAddedDescription_ = false;
65        this->bIsVector_ = false;
66
67        this->defvalueString_ = defvalue.toString();
68        this->update();
69    }
70
71    /**
72        @brief Constructor: Converts the default-value to a string, checks the config-file for a changed value, sets the intern value variable.
73        @param type The type of the corresponding config-file
74        @param identifier The identifier of the class the variable belongs to
75        @param varname The name of the variable
76        @param defvalue The default-value
77    */
78    ConfigValueContainer::ConfigValueContainer(ConfigFileType type, Identifier* identifier, const std::string& varname, const std::vector<MultiTypeMath>& defvalue)
79    {
80        this->type_ = type;
81        this->identifier_ = identifier;
82        this->sectionname_ = identifier->getName();
83        this->varname_ = varname;
84
85        this->valueVector_ = defvalue;
86        this->bAddedDescription_ = false;
87        this->bIsVector_ = true;
88
89        if (defvalue.size() > 0)
90        {
91                this->value_ = defvalue[0];
92
93            for (unsigned int i = 0; i < defvalue.size(); i++)
94            {
95                ConfigFileManager::getSingleton()->getValue(this->type_, this->sectionname_, this->varname_, i, defvalue[i].toString(), this->value_.isA(MT_string));
96                this->defvalueStringVector_.push_back(defvalue[i].toString());
97            }
98
99            this->update();
100        }
101    }
102
103    /**
104        @brief Destructor: Deletes the callback object if necessary.
105    */
106    ConfigValueContainer::~ConfigValueContainer()
107    {
108        if (this->callback_)
109            delete this->callback_;
110    }
111
112    /**
113        @brief Assigns a new value to the config-value of all objects and writes the change into the config-file.
114        @param input The new value
115        @return True if the new value was successfully assigned
116    */
117    bool ConfigValueContainer::set(const MultiTypeMath& input)
118    {
119        if (this->bIsVector_)
120        {
121            return this->callFunctionWithIndex(&ConfigValueContainer::set, input.toString());
122        }
123        else
124        {
125            if (this->tset(input))
126            {
127                ConfigFileManager::getSingleton()->setValue(this->type_, this->sectionname_, this->varname_, input.toString(), this->value_.isA(MT_string));
128                return true;
129            }
130        }
131        return false;
132    }
133
134    /**
135        @brief Assigns a new value to the config-value of all objects and writes the change into the config-file.
136        @param index The index in the vector
137        @param input The new value
138        @return True if the new value was successfully assigned
139    */
140    bool ConfigValueContainer::set(unsigned int index, const MultiTypeMath& input)
141    {
142        if (this->bIsVector_)
143        {
144            if (this->tset(index, input))
145            {
146                ConfigFileManager::getSingleton()->setValue(this->type_, this->sectionname_, this->varname_, index, input.toString(), this->value_.isA(MT_string));
147                return true;
148            }
149        }
150        else
151        {
152            COUT(1) << "Error: Config-value '" << this->varname_ << "' in " << this->sectionname_ << " is not a vector." << std::endl;
153        }
154        return false;
155    }
156
157    /**
158        @brief Assigns a new value to the config-value of all objects, but doesn't change the config-file (t stands for temporary).
159        @param input The new value. If bIsVector_ then write "index value"
160        @return True if the new value was successfully assigned
161    */
162    bool ConfigValueContainer::tset(const MultiTypeMath& input)
163    {
164        if (this->bIsVector_)
165        {
166            return this->callFunctionWithIndex(&ConfigValueContainer::tset, input.toString());
167        }
168        else
169        {
170            MultiTypeMath temp = this->value_;
171            if (temp.assimilate(input))
172            {
173                this->value_ = temp;
174                if (this->identifier_)
175                    this->identifier_->updateConfigValues();
176
177                return true;
178            }
179        }
180        return false;
181    }
182
183    /**
184        @brief Assigns a new value to the config-value of all objects, but doesn't change the config-file (t stands for temporary).
185        @param index The index in the vector
186        @param input The new value
187        @return True if the new value was successfully assigned
188    */
189    bool ConfigValueContainer::tset(unsigned int index, const MultiTypeMath& input)
190    {
191        if (this->bIsVector_)
192        {
193            if (index > MAX_VECTOR_INDEX)
194            {
195                COUT(1) << "Error: Index " << index << " is too large." << std::endl;
196                return false;
197            }
198
199            if (index >= this->valueVector_.size())
200            {
201                for (unsigned int i = this->valueVector_.size(); i <= index; i++)
202                {
203                    this->valueVector_.push_back(MultiTypeMath());
204                }
205            }
206
207            MultiTypeMath temp = this->value_;
208            if (temp.assimilate(input))
209            {
210                this->valueVector_[index] = temp;
211
212                if (this->identifier_)
213                    this->identifier_->updateConfigValues();
214
215                return true;
216            }
217        }
218        else
219        {
220            COUT(1) << "Error: Config-value '" << this->varname_ << "' in " << this->sectionname_ << " is not a vector." << std::endl;
221        }
222        return false;
223    }
224
225    /**
226        @brief Adds a new entry to the end of the vector.
227        @param input The new entry
228        @return True if the new entry was successfully added
229    */
230    bool ConfigValueContainer::add(const MultiTypeMath& input)
231    {
232        if (this->bIsVector_)
233            return this->set(this->valueVector_.size(), input);
234
235        COUT(1) << "Error: Config-value '" << this->varname_ << "' in " << this->sectionname_ << " is not a vector." << std::endl;
236        return false;
237    }
238
239    /**
240        @brief Removes an existing entry from the vector.
241        @param index The index of the entry
242        @return True if the entry was removed
243    */
244    bool ConfigValueContainer::remove(unsigned int index)
245    {
246        if (this->bIsVector_)
247        {
248            if (index < this->valueVector_.size())
249            {
250                // Erase the entry from the vector, change (shift) all entries beginning with index in the config file, remove the last entry from the file
251                this->valueVector_.erase(this->valueVector_.begin() + index);
252                for (unsigned int i = index; i < this->valueVector_.size(); i++)
253                    ConfigFileManager::getSingleton()->setValue(this->type_, this->sectionname_, this->varname_, i, this->valueVector_[i], this->value_.isA(MT_string));
254                ConfigFileManager::getSingleton()->deleteVectorEntries(this->type_, this->sectionname_, this->varname_, this->valueVector_.size());
255
256                return true;
257            }
258            COUT(1) << "Error: Invalid vector-index." << std::endl;
259        }
260
261        COUT(1) << "Error: Config-value '" << this->varname_ << "' in " << this->sectionname_ << " is not a vector." << std::endl;
262        return false;
263    }
264
265    /**
266        @brief Sets the value of the variable back to the default value and resets the config-file entry.
267    */
268    bool ConfigValueContainer::reset()
269    {
270        if (!this->bIsVector_)
271            return this->set(this->defvalueString_);
272        else
273        {
274            bool success = true;
275            for (unsigned int i = 0; i < this->defvalueStringVector_.size(); i++)
276                if (!this->set(i, this->defvalueStringVector_[i]))
277                    success = false;
278            ConfigFileManager::getSingleton()->deleteVectorEntries(this->type_, this->sectionname_, this->varname_, this->defvalueStringVector_.size());
279            return success;
280        }
281    }
282
283    /**
284        @brief Retrieves the configured value from the currently loaded config-file.
285    */
286    void ConfigValueContainer::update()
287    {
288        if (!this->bIsVector_)
289            this->value_.fromString(ConfigFileManager::getSingleton()->getValue(this->type_, this->sectionname_, this->varname_, this->defvalueString_, this->value_.isA(MT_string)));
290        else
291        {
292            this->valueVector_.clear();
293            for (unsigned int i = 0; i < ConfigFileManager::getSingleton()->getVectorSize(this->type_, this->sectionname_, this->varname_); i++)
294            {
295                if (i < this->defvalueStringVector_.size())
296                {
297                    this->value_.fromString(ConfigFileManager::getSingleton()->getValue(this->type_, this->sectionname_, this->varname_, i, this->defvalueStringVector_[i], this->value_.isA(MT_string)));
298                }
299                else
300                {
301                    this->value_.fromString(ConfigFileManager::getSingleton()->getValue(this->type_, this->sectionname_, this->varname_, i, MultiTypeMath(), this->value_.isA(MT_string)));
302                }
303
304                this->valueVector_.push_back(this->value_);
305            }
306        }
307    }
308
309    /**
310        @brief Calls the given function with parsed index and the parsed argument from the input string.
311        @param function The function to call
312        @param input The input string
313        @return The returnvalue of the functioncall
314    */
315    bool ConfigValueContainer::callFunctionWithIndex(bool (ConfigValueContainer::* function) (unsigned int, const MultiTypeMath&), const std::string& input)
316    {
317        SubString token(input, " ", SubString::WhiteSpaces, true, '\\', false, '"', false, '(', ')', false, '\0');
318        int index = -1;
319        bool success = false;
320
321        if (token.size() > 0)
322            success = ConvertValue(&index, token[0]);
323
324        if (!success || index < 0 || index > MAX_VECTOR_INDEX)
325        {
326            if (!success)
327            {
328                COUT(1) << "Error: Config-value '" << this->varname_ << "' in " << this->sectionname_ << " is a vector." << std::endl;
329            }
330            else
331            {
332                COUT(1) << "Error: Invalid vector-index." << std::endl;
333            }
334            return false;
335        }
336
337        if (token.size() >= 2)
338            return (this->*function)(index, token.subSet(1).join());
339        else
340            return (this->*function)(index, "");
341    }
342
343    /**
344        @brief Adds a description to the config-value.
345        @param description The description
346    */
347    ConfigValueContainer& ConfigValueContainer::description(const std::string& description)
348    {
349        if (!this->bAddedDescription_)
350        {
351            this->description_ = std::string("ConfigValueDescription::" + this->identifier_->getName() + "::" + this->varname_);
352            AddLanguageEntry(this->description_, description);
353            this->bAddedDescription_ = true;
354        }
355        return (*this);
356    }
357
358    /**
359        @brief Returns the description of the config-value.
360        @return The description
361    */
362    const std::string& ConfigValueContainer::getDescription() const
363    {
364        return GetLocalisation(this->description_);
365    }
366}
Note: See TracBrowser for help on using the repository browser.