Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 3936 was 3280, checked in by rgrieder, 15 years ago

Merged most of the core4 revisions back to the trunk except for:

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