Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/libraries/core/config/ConfigValueContainer.cc

Last change on this file was 11071, checked in by landauf, 9 years ago

merged branch cpp11_v3 back to trunk

  • Property svn:eol-style set to native
File size: 12.6 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"
[9558]38#include "core/Language.h"
[6536]39#include "ConfigFileManager.h"
[9559]40#include "SettingsConfigFile.h"
[1505]41
42namespace orxonox
43{
[1791]44    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]45
[1505]46    /**
[6536]47        @brief Initializes the ConfigValueContainer with default values.
[1505]48    */
[6536]49    void ConfigValueContainer::init(ConfigFileType::Value type, Identifier* identifier, const std::string& sectionname, const std::string& varname)
[1505]50    {
51        this->type_ = type;
52        this->identifier_ = identifier;
[1887]53        this->sectionname_ = sectionname;
[1505]54        this->varname_ = varname;
[11071]55        this->callback_ = nullptr;
[1747]56        this->bContainerIsNew_ = true;
57        this->bDoInitialCallback_ = false;
58        this->bAddedDescription_ = false;
[6536]59
60        // Register containers for general settings
61        if (this->type_ == ConfigFileType::Settings)
62            SettingsConfigFile::getInstance().addConfigValueContainer(this);
[1747]63    }
[1505]64
[1747]65    /**
66        @brief Does some special initialization for single config-values.
67    */
68    void ConfigValueContainer::initValue(const MultiType& defvalue)
69    {
[1505]70        this->value_ = defvalue;
71        this->bIsVector_ = false;
72
[9550]73        this->defvalueString_ = this->value_.get<std::string>();
[1505]74        this->update();
75    }
76
77    /**
[1747]78        @brief Does some special initialization for vector config-values.
[1505]79    */
[1747]80    void ConfigValueContainer::initVector()
[1505]81    {
82        this->bIsVector_ = true;
83
[1747]84        for (unsigned int i = 0; i < this->valueVector_.size(); i++)
[1505]85        {
[9550]86            ConfigFileManager::getInstance().getConfigFile(this->type_)->getOrCreateValue(this->sectionname_, this->varname_, i, this->valueVector_[i], this->value_.isType<std::string>());
[1747]87            this->defvalueStringVector_.push_back(this->valueVector_[i]);
88        }
[1505]89
[1747]90        this->update();
91    }
[1505]92
[1747]93    /**
94        @brief Destructor: Deletes the callback object if necessary.
95    */
96    ConfigValueContainer::~ConfigValueContainer()
97    {
98        if (this->callback_)
99            delete this->callback_;
[6536]100
101        // Unregister general settings containers
102        if (this->type_ == ConfigFileType::Settings && SettingsConfigFile::exists())
103            SettingsConfigFile::getInstance().removeConfigValueContainer(this);
[1505]104    }
105
106    /**
107        @brief Assigns a new value to the config-value of all objects and writes the change into the config-file.
108        @param input The new value
109        @return True if the new value was successfully assigned
110    */
[1747]111    bool ConfigValueContainer::set(const MultiType& input)
[1505]112    {
113        if (this->bIsVector_)
114        {
[1747]115            return this->callFunctionWithIndex(&ConfigValueContainer::set, input);
[1505]116        }
117        else
118        {
119            if (this->tset(input))
120            {
[9550]121                ConfigFileManager::getInstance().getConfigFile(this->type_)->setValue(this->sectionname_, this->varname_, input, this->value_.isType<std::string>());
[1505]122                return true;
123            }
124        }
125        return false;
126    }
127
128    /**
129        @brief Assigns a new value to the config-value of all objects and writes the change into the config-file.
130        @param index The index in the vector
131        @param input The new value
132        @return True if the new value was successfully assigned
133    */
[1747]134    bool ConfigValueContainer::set(unsigned int index, const MultiType& input)
[1505]135    {
136        if (this->bIsVector_)
137        {
138            if (this->tset(index, input))
139            {
[9550]140                ConfigFileManager::getInstance().getConfigFile(this->type_)->setValue(this->sectionname_, this->varname_, index, input, this->value_.isType<std::string>());
[1505]141                return true;
142            }
143        }
144        else
145        {
[8858]146            orxout(user_error, context::config) << "Config-value '" << this->varname_ << "' in " << this->sectionname_ << " is not a vector." << endl;
[1505]147        }
148        return false;
149    }
150
151    /**
152        @brief Assigns a new value to the config-value of all objects, but doesn't change the config-file (t stands for temporary).
153        @param input The new value. If bIsVector_ then write "index value"
154        @return True if the new value was successfully assigned
155    */
[1747]156    bool ConfigValueContainer::tset(const MultiType& input)
[1505]157    {
158        if (this->bIsVector_)
159        {
[1747]160            return this->callFunctionWithIndex(&ConfigValueContainer::tset, input);
[1505]161        }
162        else
163        {
[1747]164            this->value_ = input;
[1505]165
[1747]166            if (this->identifier_)
167                this->identifier_->updateConfigValues();
168
169            return true;
[1505]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    */
[1747]179    bool ConfigValueContainer::tset(unsigned int index, const MultiType& input)
[1505]180    {
181        if (this->bIsVector_)
182        {
183            if (index > MAX_VECTOR_INDEX)
184            {
[8858]185                orxout(user_error, context::config) << "Index " << index << " is too large." << endl;
[1505]186                return false;
187            }
188
189            if (index >= this->valueVector_.size())
190            {
191                for (unsigned int i = this->valueVector_.size(); i <= index; i++)
192                {
[11071]193                    this->valueVector_.emplace_back();
[1505]194                }
195            }
196
[1747]197            this->valueVector_[index] = input;
[1505]198
[1747]199            if (this->identifier_)
200                this->identifier_->updateConfigValues();
[1505]201
[1747]202            return true;
[1505]203        }
204        else
205        {
[8858]206            orxout(user_error, context::config) << "Config-value '" << this->varname_ << "' in " << this->sectionname_ << " is not a vector." << endl;
[1747]207            return false;
[1505]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    */
[1747]216    bool ConfigValueContainer::add(const MultiType& input)
[1505]217    {
218        if (this->bIsVector_)
219            return this->set(this->valueVector_.size(), input);
220
[8858]221        orxout(user_error, context::config) << "Config-value '" << this->varname_ << "' in " << this->sectionname_ << " is not a vector." << endl;
[1505]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++)
[9550]239                    ConfigFileManager::getInstance().getConfigFile(this->type_)->setValue(this->sectionname_, this->varname_, i, this->valueVector_[i], this->value_.isType<std::string>());
[6536]240                ConfigFileManager::getInstance().getConfigFile(this->type_)->deleteVectorEntries(this->sectionname_, this->varname_, this->valueVector_.size());
[1505]241
242                return true;
243            }
[8858]244            orxout(user_error, context::config) << "Invalid vector-index." << endl;
[1505]245        }
246
[8858]247        orxout(user_error, context::config) << "Config-value '" << this->varname_ << "' in " << this->sectionname_ << " is not a vector." << endl;
[1505]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;
[6536]264            ConfigFileManager::getInstance().getConfigFile(this->type_)->deleteVectorEntries(this->sectionname_, this->varname_, this->defvalueStringVector_.size());
[1505]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_)
[9550]275            this->value_ = ConfigFileManager::getInstance().getConfigFile(this->type_)->getOrCreateValue(this->sectionname_, this->varname_, this->defvalueString_, this->value_.isType<std::string>());
[1505]276        else
277        {
278            this->valueVector_.clear();
[6536]279            unsigned int vectorSize = ConfigFileManager::getInstance().getConfigFile(this->type_)->getVectorSize(this->sectionname_, this->varname_);
[2662]280            for (unsigned int i = 0; i < vectorSize; i++)
[1505]281            {
282                if (i < this->defvalueStringVector_.size())
283                {
[9550]284                    this->value_ = ConfigFileManager::getInstance().getConfigFile(this->type_)->getOrCreateValue(this->sectionname_, this->varname_, i, this->defvalueStringVector_[i], this->value_.isType<std::string>());
[1505]285                }
286                else
287                {
[9550]288                    this->value_ = ConfigFileManager::getInstance().getConfigFile(this->type_)->getOrCreateValue(this->sectionname_, this->varname_, i, MultiType(), this->value_.isType<std::string>());
[1505]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    */
[1747]302    bool ConfigValueContainer::callFunctionWithIndex(bool (ConfigValueContainer::* function) (unsigned int, const MultiType&), const std::string& input)
[1505]303    {
[7284]304        SubString token(input, " ", SubString::WhiteSpaces, true, '\\', false, '"', false, '\0', '\0', false, '\0');
[1505]305        int index = -1;
306        bool success = false;
307
308        if (token.size() > 0)
[3196]309            success = convertValue(&index, token[0]);
[1505]310
[1791]311        if (!success || index < 0 || index > (signed int)MAX_VECTOR_INDEX)
[1505]312        {
313            if (!success)
314            {
[8858]315                orxout(user_error, context::config) << "Config-value '" << this->varname_ << "' in " << this->sectionname_ << " is a vector." << endl;
[1505]316            }
317            else
318            {
[8858]319                orxout(user_error, context::config) << "Invalid vector-index." << endl;
[1505]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    */
[1747]334    ConfigValueContainer& ConfigValueContainer::description(const std::string& description)
[1505]335    {
336        if (!this->bAddedDescription_)
337        {
[1887]338            this->description_ = std::string("ConfigValueDescription::" + this->sectionname_ + "::" + this->varname_);
[1505]339            AddLanguageEntry(this->description_, description);
340            this->bAddedDescription_ = true;
341        }
[1747]342        return (*this);
[1505]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.