Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/output/src/libraries/core/ConfigValueContainer.cc @ 9215

Last change on this file since 9215 was 8806, checked in by landauf, 13 years ago

Replaced COUT with orxout in core. Tried to set levels and contexts in a more or less useful way, but not really optimized.

  • 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_.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().getConfigFile(this->type_)->getOrCreateValue(this->sectionname_, this->varname_, i, this->valueVector_[i], this->value_.isType(MT_Type::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(MT_Type::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(MT_Type::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(MT_Type::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(MT_Type::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(MT_Type::String));
284                }
285                else
286                {
287                    this->value_ = ConfigFileManager::getInstance().getConfigFile(this->type_)->getOrCreateValue(this->sectionname_, this->varname_, i, MultiType(), this->value_.isType(MT_Type::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.