Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/console/src/core/ConfigValueContainer.cc @ 1324

Last change on this file since 1324 was 1324, checked in by landauf, 17 years ago

Added a command-history to the console. you can scroll through all previously entered commands by pressing [up] key.
The history is stored in orxonox.ini in the section [Shell]. You can configure the maximal amount of stored commands (default: 100).
This allows you to use the history after orxonox was restarted.
The history uses a cyclic vector (with the configured size), meaning the newest command will overwrite the oldest entry (if the maximal size was reached).

additionally I fixed some bugs in ConfigValueContainer and added a mod-function to Math.h, that does basically the same as %, but without returning a negative value in case of a negative input.

-1 % 10 = -1
-11 % 10 = -1

mod(-1, 10) = 9
mod(-11, 10) = 9

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