Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/libraries/core/ConfigValueContainer.cc @ 9655

Last change on this file since 9655 was 9550, checked in by landauf, 12 years ago

merged testing branch back to trunk. unbelievable it took me 13 months to finish this chore…

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