Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

Added getXXX() functions to MultiType, where XXX stands for any supported typename.
getString() replaces toString().
Like in getValue(type* pointer), the current value gets converted to the requested type. It's basically just a call to the convert-operator, so (1) "type a = mymultitype;", (2) "type a; mymultitype.getValue(&a);" and (3) "type a = get'Type'();" are equivalent, but the implicit cast (1) may be ambiguous.

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