Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/tutoriallevel/src/libraries/core/ConfigFileManager.cc @ 8119

Last change on this file since 8119 was 7401, checked in by landauf, 14 years ago

merged doc branch back to trunk

  • Property svn:eol-style set to native
File size: 29.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 ConfigFileManager and its helper classes.
32*/
33
34#include "ConfigFileManager.h"
35
36#include <boost/filesystem.hpp>
37
38#include "util/Convert.h"
39#include "util/Math.h"
40#include "util/StringUtils.h"
41#include "ConfigValueContainer.h"
42#include "PathConfig.h"
43#include "command/ConsoleCommand.h"
44
45namespace orxonox
46{
47    //////////////////////////
48    // ConfigFileEntryValue //
49    //////////////////////////
50    /**
51        @brief Updates the string that will be stored in the file after one of it's components (name, value, comment) has changed.
52    */
53    void ConfigFileEntryValue::update()
54    {
55        // Make sure we remove the quotes when bString changes
56        if (this->bString_)
57            this->value_ = stripEnclosingQuotes(this->value_);
58        // Assemble the entry line
59        this->fileEntry_ = this->getKeyString() + " = ";
60        if (this->bString_ && !this->value_.empty())
61            this->fileEntry_ += '"' + addSlashes(this->value_) + '"';
62        else
63            this->fileEntry_ += this->value_;
64        if (!this->additionalComment_.empty())
65            this->fileEntry_ += ' ' + this->additionalComment_;
66    }
67
68
69    ////////////////////////////////
70    // ConfigFileEntryVectorValue //
71    ////////////////////////////////
72    /**
73        @brief Updates the string that will be stored in the file after one of it's components (name, value, index, comment) has changed.
74    */
75    void ConfigFileEntryVectorValue::update()
76    {
77        this->keyString_ = this->name_ + '[' + multi_cast<std::string>(this->index_) + ']';
78        ConfigFileEntryValue::update();
79    }
80
81
82    ///////////////////////
83    // ConfigFileSection //
84    ///////////////////////
85    /**
86        @brief Destructor: Deletes all entries.
87    */
88    ConfigFileSection::~ConfigFileSection()
89    {
90        for (std::list<ConfigFileEntry*>::iterator it = this->entries_.begin(); it != this->entries_.end(); )
91            delete (*(it++));
92    }
93
94    /**
95        @brief Deletes all elements of a config vector if their index is greater or equal to @a startindex.
96
97        @param name         The name of the vector
98        @param startindex   The index of the first element that will be deleted
99    */
100    void ConfigFileSection::deleteVectorEntries(const std::string& name, unsigned int startindex)
101    {
102        for (std::list<ConfigFileEntry*>::iterator it = this->entries_.begin(); it != this->entries_.end(); )
103        {
104            if (((*it)->getName() == name) && ((*it)->getIndex() >= startindex))
105            {
106                delete (*it);
107                this->entries_.erase(it++);
108            }
109            else
110            {
111                ++it;
112            }
113        }
114    }
115
116    /**
117        @brief Returns the size of a config vector.
118        @param name     The name of the vector
119    */
120    unsigned int ConfigFileSection::getVectorSize(const std::string& name) const
121    {
122        unsigned int size = 0;
123        for (std::list<ConfigFileEntry*>::const_iterator it = this->entries_.begin(); it != this->entries_.end(); ++it)
124            if ((*it)->getName() == name)
125                if ((*it)->getIndex() > size)
126                    size = (*it)->getIndex();
127        if (size == 0)
128            return 0;
129        else
130            return (size + 1);
131    }
132
133    /**
134        @brief Returns the title and comment of the section as it will be stored in the file.
135    */
136    std::string ConfigFileSection::getFileEntry() const
137    {
138        if (this->additionalComment_.empty())
139            return ('[' + this->name_ + ']');
140        else
141            return ('[' + this->name_ + "] " + this->additionalComment_);
142    }
143
144    /**
145        @brief Returns the entry with given name (or NULL if it doesn't exist).
146
147        @param name     The name of the entry
148    */
149    ConfigFileEntry* ConfigFileSection::getEntry(const std::string& name) const
150    {
151        for (std::list<ConfigFileEntry*>::const_iterator it = this->entries_.begin(); it != this->entries_.end(); ++it)
152        {
153            if ((*it)->getName() == name)
154                return *it;
155        }
156        return NULL;
157    }
158
159    /**
160        @brief Returns the entry of a vector element with given name and index (or NULL if it doesn't exist).
161
162        @param name     The name of the vector
163        @param index    The index of the element in the vector
164    */
165    ConfigFileEntry* ConfigFileSection::getEntry(const std::string& name, unsigned int index) const
166    {
167        for (std::list<ConfigFileEntry*>::const_iterator it = this->entries_.begin(); it != this->entries_.end(); ++it)
168        {
169            if (((*it)->getName() == name) && ((*it)->getIndex() == index))
170                return *it;
171        }
172        return NULL;
173    }
174
175    /**
176        @brief Returns the iterator to the entry with given name. If the entry doesn't exist, it is created using the fallback value.
177
178        @param name     The name of the entry
179        @param fallback The value that will be used if the entry doesn't exist
180        @param bString  If true, the value is treated as string which means some special treatment of special characters.
181    */
182    std::list<ConfigFileEntry*>::iterator ConfigFileSection::getOrCreateEntryIterator(const std::string& name, const std::string& fallback, bool bString)
183    {
184        for (std::list<ConfigFileEntry*>::iterator it = this->entries_.begin(); it != this->entries_.end(); ++it)
185        {
186            if ((*it)->getName() == name)
187            {
188                (*it)->setString(bString);
189                return it;
190            }
191        }
192
193        this->bUpdated_ = true;
194
195        return this->entries_.insert(this->entries_.end(), new ConfigFileEntryValue(name, fallback, bString));
196    }
197
198    /**
199        @brief Returns the iterator to the entry of a vector element with given name and index. If the entry doesn't exist, it is created using the fallback value.
200
201        @param name     The name of the vector
202        @param index    The index of the element in the vector
203        @param fallback The value that will be used if the entry doesn't exist
204        @param bString  If true, the value is treated as string which means some special treatment of special characters.
205    */
206    std::list<ConfigFileEntry*>::iterator ConfigFileSection::getOrCreateEntryIterator(const std::string& name, unsigned int index, const std::string& fallback, bool bString)
207    {
208        for (std::list<ConfigFileEntry*>::iterator it = this->entries_.begin(); it != this->entries_.end(); ++it)
209        {
210            if (((*it)->getName() == name) && ((*it)->getIndex() == index))
211            {
212                (*it)->setString(bString);
213                return it;
214            }
215        }
216
217        this->bUpdated_ = true;
218
219        if (index == 0)
220            return this->entries_.insert(this->entries_.end(), new ConfigFileEntryVectorValue(name, index, fallback, bString));
221        else
222            return this->entries_.insert(++this->getOrCreateEntryIterator(name, index - 1, "", bString), new ConfigFileEntryVectorValue(name, index, fallback, bString));
223    }
224
225
226    ////////////////
227    // ConfigFile //
228    ////////////////
229
230    const char* ConfigFile::DEFAULT_CONFIG_FOLDER = "defaultConfig";
231
232    /**
233        @brief Constructor: Initializes the config file.
234        @param filename The file-name of this config file
235        @param bCopyFallbackFile If true, the default config file is copied into the config-directory before loading the file
236    */
237    ConfigFile::ConfigFile(const std::string& filename, bool bCopyFallbackFile)
238        : filename_(filename)
239        , bCopyFallbackFile_(bCopyFallbackFile)
240        , bUpdated_(false)
241    {
242    }
243
244    /**
245        @brief Destructor: Deletes all sections and entries.
246    */
247    ConfigFile::~ConfigFile()
248    {
249        this->clear();
250    }
251
252    /**
253        @brief Loads the config file from the hard-disk and reads the sections and their values.
254    */
255    void ConfigFile::load()
256    {
257        // Be sure we start from new in the memory
258        this->clear();
259
260        boost::filesystem::path filepath(this->filename_);
261        if (!filepath.is_complete())
262        {
263            filepath = PathConfig::getConfigPath() / filepath;
264            if (this->bCopyFallbackFile_)
265            {
266                // Look for default file in the data folder
267                if (!boost::filesystem::exists(filepath))
268                {
269                    boost::filesystem::path defaultFilepath(PathConfig::getDataPath() / DEFAULT_CONFIG_FOLDER / this->filename_);
270                    if (boost::filesystem::exists(defaultFilepath))
271                    {
272                        // Try to copy default file from the data folder
273                        try
274                        {
275                            boost::filesystem::copy_file(defaultFilepath, filepath);
276                            COUT(3) << "Copied " << this->filename_ << " from the default config folder." << std::endl;
277                        }
278                        catch (const boost::filesystem::filesystem_error& ex)
279                        { COUT(1) << "Error in ConfigFile: " << ex.what() << std::endl; }
280                    }
281                }
282            }
283        }
284
285        // Open the file
286        std::ifstream file;
287        file.open(filepath.string().c_str(), std::fstream::in);
288        if (file.is_open())
289        {
290            ConfigFileSection* newsection = 0;
291
292            while (file.good() && !file.eof())
293            {
294                std::string line;
295                std::getline(file, line);
296
297                const std::string& temp = getStripped(line);
298                if (!isEmpty(temp) && !isComment(temp))
299                {
300                    size_t   pos1 = temp.find('[');
301                    if (pos1 == 0) pos1 = line.find('['); else pos1 = std::string::npos;
302                    size_t   pos2 = line.find(']');
303
304                    if (pos1 != std::string::npos && pos2 != std::string::npos && pos2 > pos1 + 1)
305                    {
306                        // New section
307                        const std::string& comment = line.substr(pos2 + 1);
308                        if (isComment(comment))
309                            newsection = new ConfigFileSection(line.substr(pos1 + 1, pos2 - pos1 - 1), comment);
310                        else
311                            newsection = new ConfigFileSection(line.substr(pos1 + 1, pos2 - pos1 - 1));
312                        this->sections_.insert(this->sections_.end(), newsection);
313                        continue;
314                    }
315                }
316
317                if (newsection != 0)
318                {
319                    if (isComment(line))
320                    {
321                        // New comment
322                        newsection->getEntries().insert(newsection->getEntries().end(), new ConfigFileEntryComment(removeTrailingWhitespaces(line)));
323                        continue;
324                    }
325                    else
326                    {
327                        size_t pos1 = line.find('=');
328
329                        if (pos1 != std::string::npos && pos1 > 0)
330                        {
331                            // New entry
332                            size_t pos2 = line.find('[');
333                            size_t pos3 = line.find(']');
334                            size_t commentposition = getNextCommentPosition(line, pos1 + 1);
335                            while (isBetweenQuotes(line, commentposition))
336                            {
337                                commentposition = getNextCommentPosition(line, commentposition + 1);
338                            }
339                            std::string value, comment;
340                            if (commentposition == std::string::npos)
341                            {
342                                value = line.substr(pos1 + 1);
343                            }
344                            else
345                            {
346                                value = line.substr(pos1 + 1, commentposition - pos1 - 1);
347                                comment = removeTrailingWhitespaces(line.substr(commentposition));
348                            }
349
350                            value = removeTrailingWhitespaces(value);
351                            value = removeSlashes(value);
352
353                            if (pos2 != std::string::npos && pos3 != std::string::npos && pos3 > pos2 + 1)
354                            {
355                                // There might be an array index
356                                unsigned int index = 0;
357                                if (convertValue(&index, line.substr(pos2 + 1, pos3 - pos2 - 1)))
358                                {
359                                    // New array
360                                    std::list<ConfigFileEntry*>::iterator it = newsection->getOrCreateEntryIterator(getStripped(line.substr(0, pos2)), index, value, false);
361                                    (*it)->setValue(value);
362                                    (*it)->setComment(comment);
363                                    continue;
364                                }
365                            }
366
367                            // New value
368                            newsection->getEntries().insert(newsection->getEntries().end(), new ConfigFileEntryValue(getStripped(line.substr(0, pos1)), value, false, comment));
369                            continue;
370                        }
371                    }
372                }
373            }
374
375            file.close();
376
377            COUT(3) << "Loaded config file \"" << this->filename_ << "\"." << std::endl;
378
379            // DO NOT save the file --> we can open supposedly read only config files
380        } // end file.is_open()
381    }
382
383    /**
384        @brief Writes the sections and values to the hard-disk.
385    */
386    void ConfigFile::save() const
387    {
388        this->saveAs(this->filename_);
389    }
390
391    /**
392        @brief Writes the sections and values to a given file on the hard-disk.
393    */
394    void ConfigFile::saveAs(const std::string& filename) const
395    {
396        boost::filesystem::path filepath(filename);
397        if (!filepath.is_complete())
398            filepath = PathConfig::getConfigPath() / filename;
399        std::ofstream file;
400        file.open(filepath.string().c_str(), std::fstream::out);
401        file.setf(std::ios::fixed, std::ios::floatfield);
402        file.precision(6);
403
404        if (!file.is_open())
405        {
406            COUT(1) << "Error: Couldn't open config-file \"" << filename << "\"." << std::endl;
407            return;
408        }
409
410        for (std::list<ConfigFileSection*>::const_iterator it = this->sections_.begin(); it != this->sections_.end(); ++it)
411        {
412            file << (*it)->getFileEntry() << std::endl;
413
414            for (std::list<ConfigFileEntry*>::const_iterator it_entries = (*it)->getEntriesBegin(); it_entries != (*it)->getEntriesEnd(); ++it_entries)
415                file << (*it_entries)->getFileEntry() << std::endl;
416
417            file << std::endl;
418        }
419
420        file.close();
421
422        COUT(4) << "Saved config file \"" << filename << "\"." << std::endl;
423    }
424
425    /**
426        @brief Deletes all sections (which again delete all their values) and clears the list of sections.
427    */
428    void ConfigFile::clear()
429    {
430        for (std::list<ConfigFileSection*>::iterator it = this->sections_.begin(); it != this->sections_.end(); )
431            delete (*(it++));
432        this->sections_.clear();
433    }
434
435    /**
436        @brief Deletes all elements of a config vector if their index is greater or equal to @a startindex.
437
438        @param section      The name of the section
439        @param name         The name of the vector
440        @param startindex   The index of the first element that will be deleted
441    */
442    void ConfigFile::deleteVectorEntries(const std::string& section, const std::string& name, unsigned int startindex)
443    {
444        if (ConfigFileSection* sectionPtr = this->getSection(section))
445        {
446            sectionPtr->deleteVectorEntries(name, startindex);
447            this->save();
448        }
449    }
450
451    /**
452        @brief Returns a pointer to the section with given name (or NULL if the section doesn't exist).
453    */
454    ConfigFileSection* ConfigFile::getSection(const std::string& section) const
455    {
456        for (std::list<ConfigFileSection*>::const_iterator it = this->sections_.begin(); it != this->sections_.end(); ++it)
457            if ((*it)->getName() == section)
458                return (*it);
459        return NULL;
460    }
461
462    /**
463        @brief Returns a pointer to the section with given name. If it doesn't exist, the section is created.
464    */
465    ConfigFileSection* ConfigFile::getOrCreateSection(const std::string& section)
466    {
467        for (std::list<ConfigFileSection*>::iterator it = this->sections_.begin(); it != this->sections_.end(); ++it)
468            if ((*it)->getName() == section)
469                return (*it);
470
471        this->bUpdated_ = true;
472
473        return (*this->sections_.insert(this->sections_.end(), new ConfigFileSection(section)));
474    }
475
476    /**
477        @brief Saves the config file if it was updated (or if any of its sections were updated).
478    */
479    void ConfigFile::saveIfUpdated()
480    {
481        bool sectionsUpdated = false;
482
483        for (std::list<ConfigFileSection*>::iterator it = this->sections_.begin(); it != this->sections_.end(); ++it)
484        {
485            if ((*it)->bUpdated_)
486            {
487                sectionsUpdated = true;
488                (*it)->bUpdated_ = false;
489            }
490        }
491
492        if (this->bUpdated_ || sectionsUpdated)
493        {
494            this->bUpdated_ = false;
495            this->save();
496        }
497    }
498
499
500    ////////////////////////
501    // SettingsConfigFile //
502    ////////////////////////
503
504    static const std::string __CC_load_name = "reloadSettings";
505    static const std::string __CC_setFilename_name = "setSettingsFile";
506    static const std::string __CC_config_name = "config";
507    static const std::string __CC_tconfig_name = "tconfig";
508    static const std::string __CC_getConfig_name = "getConfig";
509
510    SetConsoleCommand(__CC_load_name,            &ConfigFile::load);
511    SetConsoleCommand(__CC_setFilename_name,     &SettingsConfigFile::setFilename);
512    SetConsoleCommand(__CC_config_name,          &SettingsConfigFile::config).argumentCompleter(0, autocompletion::settingssections()).argumentCompleter(1, autocompletion::settingsentries()).argumentCompleter(2, autocompletion::settingsvalue());
513    SetConsoleCommand(__CC_tconfig_name,         &SettingsConfigFile::tconfig).argumentCompleter(0, autocompletion::settingssections()).argumentCompleter(1, autocompletion::settingsentries()).argumentCompleter(2, autocompletion::settingsvalue());
514    SetConsoleCommand(__CC_getConfig_name,       &SettingsConfigFile::getConfig).argumentCompleter(0, autocompletion::settingssections()).argumentCompleter(1, autocompletion::settingsentries());
515
516    SettingsConfigFile* SettingsConfigFile::singletonPtr_s = 0;
517
518    /**
519        @brief Constructor: Activates the console commands.
520    */
521    SettingsConfigFile::SettingsConfigFile(const std::string& filename)
522        : ConfigFile(filename)
523    {
524        ModifyConsoleCommand(__CC_load_name).setObject(this);
525        ModifyConsoleCommand(__CC_setFilename_name).setObject(this);
526        ModifyConsoleCommand(__CC_config_name).setObject(this);
527        ModifyConsoleCommand(__CC_tconfig_name).setObject(this);
528        ModifyConsoleCommand(__CC_getConfig_name).setObject(this);
529    }
530
531    /**
532        @brief Destructor: Deactivates the console commands.
533    */
534    SettingsConfigFile::~SettingsConfigFile()
535    {
536        ModifyConsoleCommand(__CC_load_name).setObject(0);
537        ModifyConsoleCommand(__CC_setFilename_name).setObject(0);
538        ModifyConsoleCommand(__CC_config_name).setObject(0);
539        ModifyConsoleCommand(__CC_tconfig_name).setObject(0);
540        ModifyConsoleCommand(__CC_getConfig_name).setObject(0);
541    }
542
543    /**
544        @brief Loads the config file and updates the @ref ConfigValueContainer "config value containers".
545    */
546    void SettingsConfigFile::load()
547    {
548        ConfigFile::load();
549        this->updateConfigValues();
550    }
551
552    /**
553        @brief Changes the file-name.
554    */
555    void SettingsConfigFile::setFilename(const std::string& filename)
556    {
557        ConfigFileManager::getInstance().setFilename(ConfigFileType::Settings, filename);
558    }
559
560    /**
561        @brief Registers a new @ref ConfigValueContainer "config value container".
562    */
563    void SettingsConfigFile::addConfigValueContainer(ConfigValueContainer* container)
564    {
565        if (container == NULL)
566            return;
567        std::pair<std::string, ConfigValueContainer*> second(getLowercase(container->getName()), container);
568        this->containers_.insert(std::make_pair(getLowercase(container->getSectionName()), second));
569        this->sectionNames_.insert(container->getSectionName());
570    }
571
572    /**
573        @brief Unregisters a @ref ConfigValueContainer "config value container".
574    */
575    void SettingsConfigFile::removeConfigValueContainer(ConfigValueContainer* container)
576    {
577        if (container == NULL)
578            return;
579        const std::string& sectionLC = getLowercase(container->getSectionName());
580        ContainerMap::iterator upper = this->containers_.upper_bound(sectionLC);
581        for (ContainerMap::iterator it = this->containers_.lower_bound(sectionLC); it != upper; ++it)
582        {
583            if (it->second.second == container)
584            {
585                // Remove entry from section name set this was the last container for that section
586                if (upper == this->containers_.lower_bound(sectionLC))
587                    this->sectionNames_.erase(container->getSectionName());
588                this->containers_.erase(it);
589                break;
590            }
591        }
592    }
593
594    /**
595        @brief Updates all @ref ConfigValueContainer "config value containers".
596    */
597    void SettingsConfigFile::updateConfigValues()
598    {
599        // todo: can this be done more efficiently? looks like some identifiers will be updated multiple times.
600
601        for (ContainerMap::const_iterator it = this->containers_.begin(); it != this->containers_.end(); ++it)
602        {
603            it->second.second->update();
604            it->second.second->getIdentifier()->updateConfigValues();
605        }
606    }
607
608    /**
609        @brief Removes entries and sections from the file that don't exist anymore (i.e. if there's no corresponding @ref ConfigValueContainer "config value container").
610        @param bCleanComments If true, comments are also removed from the file
611    */
612    void SettingsConfigFile::clean(bool bCleanComments)
613    {
614        for (std::list<ConfigFileSection*>::iterator itSection = this->sections_.begin(); itSection != this->sections_.end(); )
615        {
616            const std::string& sectionLC = getLowercase((*itSection)->getName());
617            ContainerMap::const_iterator lower = this->containers_.lower_bound(sectionLC);
618            ContainerMap::const_iterator upper = this->containers_.upper_bound(sectionLC);
619            if (lower != upper)
620            {
621                // The section exists, delete comment
622                if (bCleanComments)
623                    (*itSection)->setComment("");
624                for (std::list<ConfigFileEntry*>::iterator itEntry = (*itSection)->entries_.begin(); itEntry != (*itSection)->entries_.end(); )
625                {
626                    const std::string& entryLC = getLowercase((*itEntry)->getName());
627                    bool bFound = false;
628                    for (ContainerMap::const_iterator itContainer = lower; itContainer != upper; ++itContainer)
629                    {
630                        if (itContainer->second.first == entryLC)
631                        {
632                            // The config-value exists, delete comment
633                            if (bCleanComments)
634                                (*itEntry)->setComment("");
635                            ++itEntry;
636                            bFound = true;
637                            break;
638                        }
639                    }
640                    if (!bFound)
641                    {
642                        // The config-value doesn't exist
643                        delete (*itEntry);
644                        (*itSection)->entries_.erase(itEntry++);
645                    }
646                }
647                ++itSection;
648            }
649            else
650            {
651                // The section doesn't exist
652                delete (*itSection);
653                this->sections_.erase(itSection++);
654            }
655        }
656
657        // Save the file
658        this->save();
659    }
660
661    /**
662        @brief Console-command: Changes the value of an entry and stores it the file.
663
664        @param section  The section of the config value
665        @param entry    The name of the config value
666        @param value    The new value
667    */
668    void SettingsConfigFile::config(const std::string& section, const std::string& entry, const std::string& value)
669    {
670        if (!this->configImpl(section, entry, value, &ConfigValueContainer::set))
671            COUT(1) << "Error: Config value \"" << entry << "\" in section \"" << section << "\" doesn't exist." << std::endl;
672    }
673
674    /**
675        @brief Console-command: Changes the value of an entry, but doesn't store it in the file (it's only a temporary change).
676
677        @param section  The section of the config value
678        @param entry    The name of the config value
679        @param value    The new value
680    */
681    void SettingsConfigFile::tconfig(const std::string& section, const std::string& entry, const std::string& value)
682    {
683        if (!this->configImpl(section, entry, value, &ConfigValueContainer::tset))
684            COUT(1) << "Error: Config value \"" << entry << "\" in section \"" << section << "\" doesn't exist." << std::endl;
685    }
686
687    /**
688        @brief Changes the value of an entry, depending on @a function, either by using "set" or "tset"
689
690        @param section  The section of the config value
691        @param entry    The name of the config value
692        @param value    The new value
693        @param function The function ("set" or "tset") that will be used to change the value.
694    */
695    bool SettingsConfigFile::configImpl(const std::string& section, const std::string& entry, const std::string& value, bool (ConfigValueContainer::*function)(const MultiType&))
696    {
697        const std::string& sectionLC = getLowercase(section);
698        const std::string& entryLC = getLowercase(entry);
699        ContainerMap::iterator upper = this->containers_.upper_bound(sectionLC);
700        for (ContainerMap::iterator it = this->containers_.lower_bound(sectionLC); it != upper; ++it)
701        {
702            // Note: Config value vectors cannot be supported
703            if (it->second.first == entryLC && !it->second.second->isVector())
704            {
705                return (it->second.second->*function)(value);
706            }
707        }
708        return false;
709    }
710
711    /**
712        @brief Console-command: Returns the value of a given entry.
713
714        @param section  The section of the config value
715        @param entry    The name of the config value
716    */
717    std::string SettingsConfigFile::getConfig(const std::string& section, const std::string& entry)
718    {
719        const std::string& sectionLC = getLowercase(section);
720        const std::string& entryLC = getLowercase(entry);
721        ContainerMap::iterator upper = this->containers_.upper_bound(sectionLC);
722        for (ContainerMap::iterator it = this->containers_.lower_bound(sectionLC); it != upper; ++it)
723        {
724            // Note: Config value vectors cannot be supported
725            if (it->second.first == entryLC && ! it->second.second->isVector())
726            {
727                std::string value;
728                it->second.second->getValue<std::string, OrxonoxClass>(&value, NULL);
729                return value;
730            }
731        }
732        return "";
733    }
734
735
736    ///////////////////////
737    // ConfigFileManager //
738    ///////////////////////
739
740    ConfigFileManager* ConfigFileManager::singletonPtr_s = 0;
741
742    /// Constructor: Initializes the array of config files with NULL.
743    ConfigFileManager::ConfigFileManager()
744    {
745        this->configFiles_.assign(NULL);
746    }
747
748    /// Destructor: Deletes the config files.
749    ConfigFileManager::~ConfigFileManager()
750    {
751        for (boost::array<ConfigFile*, 3>::const_iterator it = this->configFiles_.begin(); it != this->configFiles_.end(); ++it)
752            if (*it)
753                delete (*it);
754    }
755
756    /// Defines the file-name for the config file of a given type (settings, calibration, etc.).
757    void ConfigFileManager::setFilename(ConfigFileType::Value type, const std::string& filename)
758    {
759        if (this->getConfigFile(type))
760            delete this->configFiles_[type];
761        // Create and load config file
762        switch (type)
763        {
764        case ConfigFileType::Settings:
765            this->configFiles_[type] = new SettingsConfigFile(filename);
766            break;
767        case ConfigFileType::JoyStickCalibration:
768        case ConfigFileType::CommandHistory:
769            this->configFiles_[type] = new ConfigFile(filename);
770            break;
771        }
772        this->configFiles_[type]->load();
773    }
774}
Note: See TracBrowser for help on using the repository browser.