Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/core3/src/core/ConfigValueContainer.cc @ 1716

Last change on this file since 1716 was 1716, checked in by landauf, 16 years ago

Added new 'MultiType', replacing MultiTypePrimitive, MultiTypeString and MultiTypeMath. MultiType can hold all types MultiTypeMath was able to hold, namely all primitives, pointers, string and several math objects (vector2, 3 and 4, quaternion, colourvalue, radian, degree).

The new MultiType has a completely changed behaviour, I'll explain this on a wiki page somewhen.
But to say the most important things in a few words:
The MultiType has a fixed type. This type is determined by the first assigned value (by using setValue(value), operator=(value) or MultiType(value)). Every other value getting assigned later, will be converted to the first type. But you can change the type (setType<T>()), convert the value (convert<T>()) or force the type of a newly assigned value manually (setValue<T>(value)) by using template functions.

In contrast, the old MultiTypeMath changed it's internal type whenever a new type was assigned. So be aware of this important change.

At the moment I can't see any issues, but there might very well be several problems yet to discover, so further tests will be done.

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