Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/gamestate/src/libraries/core/ConfigValueContainer.cc @ 6851

Last change on this file since 6851 was 6432, checked in by rgrieder, 15 years ago

Changed the way config values associated with general settings (ConfigFileType::Settings) are handled:

  • ConfigFileManager only handles config files listed in the ConfigFileType enum (normal enum again)
  • ConfigFileManager only takes care of ConfigFiles and returns a pointer to the right one, just two functions left. —> use like: ConfigFileManager::getInstance().getConfigFile(myType)→doSomething();
  • Moved all code (except for the argument completion functions) relating to ConfigFileType::Settings to a new class: SettingsConfigFile, which is a Singleton (it doesn't make sense to have multiple instances unless you start coding a lot more)
  • SettingsConfigFile handles config value containers according to their section and entry in the ini file, not according to class and variables names. (In most cases it will be class and variable names though)
  • SettingsConfigFile supports:
    • clear() (removes any file entries not associated to a config value container)
    • updateConfigValues() (does exactly that through the identifier)
    • config, tconfig and getConfig
    • commands listed above are exported to tolua, and tconfig, config and getConfig were given shortcuts in Lua (e.g. orxonox.config)
  • If you need to organise ConfigFiles yourself, just do it without the ConfigFileManager, like the KeyBinder does.
  • All getValue() functions have been split into getOrCreateValue() and getValue(), which is const
  • Removed obsolete config value management code in the Identifier (it still stores and destroys them and provides access to them)

All of that leads to one HUGE advantage:
"config OutputHandler softDebugLevelInGameConsole"
works now :D (any further implications are up to the reader…)
(it didn't work before because the actual config value container is in the InGameConsole singleton)

  • Property svn:eol-style set to native
File size: 12.5 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            COUT(1) << "Error: Config-value '" << this->varname_ << "' in " << this->sectionname_ << " is not a vector." << std::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            return false;
161        }
162        else
163        {
164            this->value_ = input;
165
166            if (this->identifier_)
167                this->identifier_->updateConfigValues();
168
169            return true;
170        }
171    }
172
173    /**
174        @brief Assigns a new value to the config-value of all objects, but doesn't change the config-file (t stands for temporary).
175        @param index The index in the vector
176        @param input The new value
177        @return True if the new value was successfully assigned
178    */
179    bool ConfigValueContainer::tset(unsigned int index, const MultiType& input)
180    {
181        if (this->bIsVector_)
182        {
183            if (index > MAX_VECTOR_INDEX)
184            {
185                COUT(1) << "Error: Index " << index << " is too large." << std::endl;
186                return false;
187            }
188
189            if (index >= this->valueVector_.size())
190            {
191                for (unsigned int i = this->valueVector_.size(); i <= index; i++)
192                {
193                    this->valueVector_.push_back(MultiType());
194                }
195            }
196
197            this->valueVector_[index] = input;
198
199            if (this->identifier_)
200                this->identifier_->updateConfigValues();
201
202            return true;
203        }
204        else
205        {
206            COUT(1) << "Error: Config-value '" << this->varname_ << "' in " << this->sectionname_ << " is not a vector." << std::endl;
207            return false;
208        }
209    }
210
211    /**
212        @brief Adds a new entry to the end of the vector.
213        @param input The new entry
214        @return True if the new entry was successfully added
215    */
216    bool ConfigValueContainer::add(const MultiType& input)
217    {
218        if (this->bIsVector_)
219            return this->set(this->valueVector_.size(), input);
220
221        COUT(1) << "Error: Config-value '" << this->varname_ << "' in " << this->sectionname_ << " is not a vector." << std::endl;
222        return false;
223    }
224
225    /**
226        @brief Removes an existing entry from the vector.
227        @param index The index of the entry
228        @return True if the entry was removed
229    */
230    bool ConfigValueContainer::remove(unsigned int index)
231    {
232        if (this->bIsVector_)
233        {
234            if (index < this->valueVector_.size())
235            {
236                // Erase the entry from the vector, change (shift) all entries beginning with index in the config file, remove the last entry from the file
237                this->valueVector_.erase(this->valueVector_.begin() + index);
238                for (unsigned int i = index; i < this->valueVector_.size(); i++)
239                    ConfigFileManager::getInstance().getConfigFile(this->type_)->setValue(this->sectionname_, this->varname_, i, this->valueVector_[i], this->value_.isType(MT_Type::String));
240                ConfigFileManager::getInstance().getConfigFile(this->type_)->deleteVectorEntries(this->sectionname_, this->varname_, this->valueVector_.size());
241
242                return true;
243            }
244            COUT(1) << "Error: Invalid vector-index." << std::endl;
245        }
246
247        COUT(1) << "Error: Config-value '" << this->varname_ << "' in " << this->sectionname_ << " is not a vector." << std::endl;
248        return false;
249    }
250
251    /**
252        @brief Sets the value of the variable back to the default value and resets the config-file entry.
253    */
254    bool ConfigValueContainer::reset()
255    {
256        if (!this->bIsVector_)
257            return this->set(this->defvalueString_);
258        else
259        {
260            bool success = true;
261            for (unsigned int i = 0; i < this->defvalueStringVector_.size(); i++)
262                if (!this->set(i, this->defvalueStringVector_[i]))
263                    success = false;
264            ConfigFileManager::getInstance().getConfigFile(this->type_)->deleteVectorEntries(this->sectionname_, this->varname_, this->defvalueStringVector_.size());
265            return success;
266        }
267    }
268
269    /**
270        @brief Retrieves the configured value from the currently loaded config-file.
271    */
272    void ConfigValueContainer::update()
273    {
274        if (!this->bIsVector_)
275            this->value_ = ConfigFileManager::getInstance().getConfigFile(this->type_)->getOrCreateValue(this->sectionname_, this->varname_, this->defvalueString_, this->value_.isType(MT_Type::String));
276        else
277        {
278            this->valueVector_.clear();
279            unsigned int vectorSize = ConfigFileManager::getInstance().getConfigFile(this->type_)->getVectorSize(this->sectionname_, this->varname_);
280            for (unsigned int i = 0; i < vectorSize; i++)
281            {
282                if (i < this->defvalueStringVector_.size())
283                {
284                    this->value_ = ConfigFileManager::getInstance().getConfigFile(this->type_)->getOrCreateValue(this->sectionname_, this->varname_, i, this->defvalueStringVector_[i], this->value_.isType(MT_Type::String));
285                }
286                else
287                {
288                    this->value_ = ConfigFileManager::getInstance().getConfigFile(this->type_)->getOrCreateValue(this->sectionname_, this->varname_, i, MultiType(), this->value_.isType(MT_Type::String));
289                }
290
291                this->valueVector_.push_back(this->value_);
292            }
293        }
294    }
295
296    /**
297        @brief Calls the given function with parsed index and the parsed argument from the input string.
298        @param function The function to call
299        @param input The input string
300        @return The returnvalue of the functioncall
301    */
302    bool ConfigValueContainer::callFunctionWithIndex(bool (ConfigValueContainer::* function) (unsigned int, const MultiType&), const std::string& input)
303    {
304        SubString token(input, " ", SubString::WhiteSpaces, true, '\\', false, '"', false, '(', ')', false, '\0');
305        int index = -1;
306        bool success = false;
307
308        if (token.size() > 0)
309            success = convertValue(&index, token[0]);
310
311        if (!success || index < 0 || index > (signed int)MAX_VECTOR_INDEX)
312        {
313            if (!success)
314            {
315                COUT(1) << "Error: Config-value '" << this->varname_ << "' in " << this->sectionname_ << " is a vector." << std::endl;
316            }
317            else
318            {
319                COUT(1) << "Error: Invalid vector-index." << std::endl;
320            }
321            return false;
322        }
323
324        if (token.size() >= 2)
325            return (this->*function)(index, token.subSet(1).join());
326        else
327            return (this->*function)(index, "");
328    }
329
330    /**
331        @brief Adds a description to the config-value.
332        @param description The description
333    */
334    ConfigValueContainer& ConfigValueContainer::description(const std::string& description)
335    {
336        if (!this->bAddedDescription_)
337        {
338            this->description_ = std::string("ConfigValueDescription::" + this->sectionname_ + "::" + this->varname_);
339            AddLanguageEntry(this->description_, description);
340            this->bAddedDescription_ = true;
341        }
342        return (*this);
343    }
344
345    /**
346        @brief Returns the description of the config-value.
347        @return The description
348    */
349    const std::string& ConfigValueContainer::getDescription() const
350    {
351        return GetLocalisation(this->description_);
352    }
353}
Note: See TracBrowser for help on using the repository browser.