Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/core/ConfigValueContainer.cc @ 1751

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

merged core3 back to trunk

  • 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.