Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/objecthierarchy/src/core/ConfigValueContainer.cc @ 2142

Last change on this file since 2142 was 2114, checked in by rgrieder, 16 years ago

Replaced all "@file Blah.cc" with "@file" for better flexibility. DoxyGen will use the filename as default.

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