Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/core2/src/orxonox/core/ConfigFileManager.cc @ 1020

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

changed ConfigValueContainer to use ConfigFileManager, but there is still an error

File size: 15.8 KB
Line 
1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *
4 *
5 *   License notice:
6 *
7 *   This program is free software; you can redistribute it and/or
8 *   modify it under the terms of the GNU General Public License
9 *   as published by the Free Software Foundation; either version 2
10 *   of the License, or (at your option) any later version.
11 *
12 *   This program is distributed in the hope that it will be useful,
13 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
14 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 *   GNU General Public License for more details.
16 *
17 *   You should have received a copy of the GNU General Public License
18 *   along with this program; if not, write to the Free Software
19 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
20 *
21 *   Author:
22 *      Fabian 'x3n' Landau
23 *   Co-authors:
24 *      ...
25 *
26 */
27
28#include "ConfigFileManager.h"
29#include "ConsoleCommand.h"
30#include "Identifier.h"
31#include "util/Convert.h"
32#include "util/String.h"
33
34#define CONFIG_FILE_MAX_LINELENGHT 1024
35
36namespace orxonox
37{
38    ConsoleCommandShortcutExtern(reloadConfig, AccessLevel::None);
39    ConsoleCommandShortcutExtern(saveConfig, AccessLevel::None);
40    ConsoleCommandShortcutExtern(cleanConfig, AccessLevel::None);
41    ConsoleCommandShortcutExtern(loadSettings, AccessLevel::None);
42    ConsoleCommandShortcutExtern(loadKeybindings, AccessLevel::None);
43
44    void reloadConfig()
45    {
46        ConfigFileManager::getSingleton()->load();
47    }
48
49    void saveConfig()
50    {
51        ConfigFileManager::getSingleton()->save();
52    }
53
54    void cleanConfig()
55    {
56        ConfigFileManager::getSingleton()->clean();
57    }
58
59    void loadSettings(const std::string& filename)
60    {
61        ConfigFileManager::getSingleton()->setFile(CFT_Settings, filename);
62    }
63
64    void loadKeybindings(const std::string& filename)
65    {
66        ConfigFileManager::getSingleton()->setFile(CFT_Keybindings, filename);
67    }
68
69
70    //////////////////////////
71    // ConfigFileEntryValue //
72    //////////////////////////
73    std::string ConfigFileEntryValue::getFileEntry() const
74    {
75        if (this->additionalComment_ == "" || this->additionalComment_.size() == 0)
76            return (this->name_ + "=" + this->value_);
77        else
78            return (this->name_ + "=" + this->value_ + " " + this->additionalComment_);
79    }
80
81
82    ///////////////////////////////
83    // ConfigFileEntryArrayValue //
84    ///////////////////////////////
85    std::string ConfigFileEntryArrayValue::getFileEntry() const
86    {
87        if (this->additionalComment_ == "" || this->additionalComment_.size() == 0)
88            return (this->name_ + "[" + getConvertedValue<unsigned int, std::string>(this->index_, 0) + "]" + "=" + this->value_);
89        else
90            return (this->name_ + "[" + getConvertedValue<unsigned int, std::string>(this->index_, 0) + "]=" + this->value_ + " " + this->additionalComment_);
91    }
92
93
94    ///////////////////////
95    // ConfigFileSection //
96    ///////////////////////
97    ConfigFileSection::~ConfigFileSection()
98    {
99        for (std::list<ConfigFileEntry*>::iterator it = this->entries_.begin(); it != this->entries_.end(); )
100            delete (*(it++));
101    }
102
103    std::string ConfigFileSection::getFileEntry() const
104    {
105        if (this->additionalComment_ == "" || this->additionalComment_.size() == 0)
106            return (this->name_);
107        else
108            return (this->name_ + " " + this->additionalComment_);
109    }
110
111    std::list<ConfigFileEntry*>::iterator ConfigFileSection::getEntryIterator(const std::string& name, const std::string& fallback)
112    {
113std::cout << "a33333333333333333333333333\n";
114        for (std::list<ConfigFileEntry*>::iterator it = this->entries_.begin(); it != this->entries_.end(); ++it)
115            if ((*it)->getName() == name)
116                return it;
117
118        this->bUpdated_ = true;
119
120        return this->entries_.insert(this->entries_.end(), (ConfigFileEntry*)(new ConfigFileEntryValue(name, fallback)));
121    }
122
123    std::list<ConfigFileEntry*>::iterator ConfigFileSection::getEntryIterator(const std::string& name, unsigned int index, const std::string& fallback)
124    {
125std::cout << "b3333333333333333333333333\n";
126        for (std::list<ConfigFileEntry*>::iterator it = this->entries_.begin(); it != this->entries_.end(); ++it)
127            if (((*it)->getName() == name) && ((*it)->getIndex() == index))
128                return it;
129
130        this->bUpdated_ = true;
131
132        if (index == 0)
133            return this->entries_.insert(this->entries_.end(), (ConfigFileEntry*)(new ConfigFileEntryArrayValue(name, index, fallback)));
134        else
135            return this->entries_.insert(this->getEntryIterator(name, index - 1), (ConfigFileEntry*)(new ConfigFileEntryArrayValue(name, index, fallback)));
136    }
137
138
139    ////////////////
140    // ConfigFile //
141    ////////////////
142    ConfigFile::~ConfigFile()
143    {
144        for (std::list<ConfigFileSection*>::iterator it = this->sections_.begin(); it != this->sections_.end(); )
145            delete (*(it++));
146    }
147
148    void ConfigFile::load()
149    {
150        // This creates the file if it's not existing
151        std::ofstream createFile;
152        createFile.open(this->filename_.c_str(), std::fstream::app);
153        createFile.close();
154
155        // Open the file
156        std::ifstream file;
157        file.open(this->filename_.c_str(), std::fstream::in);
158
159        if (!file.is_open())
160        {
161            COUT(1) << "An error occurred in ConfigFileManager.cc:" << std::endl;
162            COUT(1) << "Error: Couldn't open config-file \"" << this->filename_ << "\"." << std::endl;
163            return;
164        }
165
166        char linearray[CONFIG_FILE_MAX_LINELENGHT];
167
168        ConfigFileSection* newsection = 0;
169
170        while (file.good() && !file.eof())
171        {
172            file.getline(linearray, CONFIG_FILE_MAX_LINELENGHT);
173
174            std::string line = std::string(linearray);
175
176            std::string temp = getStripped(line);
177            if (!isEmpty(temp) && !isComment(temp))
178            {
179                unsigned int pos1 = line.find('[');
180                unsigned int pos2 = line.find(']');
181
182                if (pos1 != std::string::npos && pos2 != std::string::npos && pos2 > pos1 + 1)
183                {
184                    // New section
185                    std::string comment = temp.substr(pos2 + 1);
186                    if (isComment(comment))
187                        newsection = new ConfigFileSection(line.substr(pos1, pos2 - pos1 + 1), comment);
188                    else
189                        newsection = new ConfigFileSection(line.substr(pos1, pos2 - pos1 + 1));
190                    this->sections_.insert(this->sections_.end(), newsection);
191                    continue;
192                }
193            }
194
195            if (newsection != 0)
196            {
197                if (isComment(line))
198                {
199std::cout << "1_7\n";
200                    // New comment
201                    newsection->getEntries().insert(newsection->getEntries().end(), new ConfigFileEntryComment(removeTrailingWhitespaces(line)));
202                    continue;
203                }
204                else
205                {
206std::cout << "1_8\n";
207                    unsigned int pos1 = line.find('=');
208
209                    if (pos1 != std::string::npos && pos1 > 0)
210                    {
211std::cout << "1_9\n";
212                        // New entry
213                        unsigned int pos2 = line.find('[');
214                        unsigned int pos3 = line.find(']');
215
216                        std::string value = removeTrailingWhitespaces(line.substr(pos1 + 1));
217                        std::string comment = "";
218
219                        std::string betweenQuotes = getStringBetweenQuotes(value);
220                        if (value.size() > 0 && value[0] == '"' && betweenQuotes != "" && betweenQuotes.size() > 0)
221                        {
222std::cout << "1_10\n";
223                            value = betweenQuotes;
224                            if (line.size() > pos1 + 1 + betweenQuotes.size() + 2)
225                                comment = removeTrailingWhitespaces(getComment(line.substr(pos1 + 1 + betweenQuotes.size() + 2)));
226                        }
227                        else
228                        {
229std::cout << "1_11\n";
230                            unsigned int pos4 = getCommentPosition(line);
231std::cout << "a\n";
232std::cout << line << std::endl;
233std::cout << line.substr(pos1 + 1, pos4 - pos1 - 1) << std::endl;
234                            value = removeTrailingWhitespaces(line.substr(pos1 + 1, pos4 - pos1 - 1));
235std::cout << value << std::endl;
236std::cout << "b\n";
237                            if (pos4 != std::string::npos)
238                                comment = removeTrailingWhitespaces(line.substr(pos4));
239std::cout << comment << std::endl;
240std::cout << "c\n";
241                        }
242
243std::cout << "1_12\n";
244                        if (pos2 != std::string::npos && pos3 != std::string::npos && pos3 > pos2 + 1)
245                        {
246std::cout << "1_13\n";
247                            // There might be an array index
248                            unsigned int index = 0;
249                            if (ConvertValue(&index, line.substr(pos2 + 1, pos3 - pos2 - 1)))
250                            {
251                                // New array
252                                newsection->getEntries().insert(newsection->getEntries().end(), new ConfigFileEntryArrayValue(getStripped(line.substr(0, pos2)), index, value, comment));
253std::cout << "1_14\n";
254                                continue;
255                            }
256                        }
257
258                        // New value
259                        newsection->getEntries().insert(newsection->getEntries().end(), new ConfigFileEntryValue(getStripped(line.substr(0, pos1)), value, comment));
260std::cout << "1_15\n";
261                        continue;
262                    }
263                }
264            }
265        }
266std::cout << "1_16\n";
267
268        file.close();
269
270        COUT(3) << "Loaded config file \"" << this->filename_ << "\"." << std::endl;
271
272        // Save the file in case something changed (like stripped whitespaces)
273        this->save();
274std::cout << "1_17\n";
275    }
276
277    void ConfigFile::save() const
278    {
279        std::ofstream file;
280        file.open(this->filename_.c_str(), std::fstream::out);
281        file.setf(std::ios::fixed, std::ios::floatfield);
282        file.precision(6);
283
284        if (!file.is_open())
285        {
286            COUT(1) << "An error occurred in ConfigFileManager.cc:" << std::endl;
287            COUT(1) << "Error: Couldn't open config-file \"" << this->filename_ << "\"." << std::endl;
288            return;
289        }
290
291        for (std::list<ConfigFileSection*>::const_iterator it = this->sections_.begin(); it != this->sections_.end(); ++it)
292        {
293            file << (*it)->getFileEntry() << std::endl;
294
295            for (std::list<ConfigFileEntry*>::const_iterator it_entries = (*it)->getEntriesBegin(); it_entries != (*it)->getEntriesEnd(); ++it_entries)
296            {
297                file << (*it_entries)->getFileEntry() << std::endl;
298            }
299
300            file << std::endl;
301        }
302
303        file.close();
304
305        COUT(4) << "Saved config file \"" << this->filename_ << "\"." << std::endl;
306    }
307
308    void ConfigFile::clean()
309    {
310    }
311
312    ConfigFileSection* ConfigFile::getSection(const std::string& section)
313    {
314std::cout << "22222222222222222222\n";
315        for (std::list<ConfigFileSection*>::iterator it = this->sections_.begin(); it != this->sections_.end(); ++it)
316            if ((*it)->getName() == section)
317                return (*it);
318
319        this->bUpdated_ = true;
320
321        return (*this->sections_.insert(this->sections_.begin(), new ConfigFileSection(section)));
322    }
323
324    void ConfigFile::saveIfUpdated()
325    {
326        bool sectionsUpdated = false;
327
328        for (std::list<ConfigFileSection*>::iterator it = this->sections_.begin(); it != this->sections_.end(); ++it)
329        {
330            if ((*it)->bUpdated_)
331            {
332                sectionsUpdated = true;
333                (*it)->bUpdated_ = false;
334            }
335        }
336
337        if (this->bUpdated_ || sectionsUpdated)
338        {
339            this->bUpdated_ = false;
340            this->save();
341        }
342    }
343
344
345    ///////////////////////
346    // ConfigFileManager //
347    ///////////////////////
348    ConfigFileManager::ConfigFileManager()
349    {
350        this->setFile(CFT_Settings, DEFAULT_CONFIG_FILE);
351    }
352
353    ConfigFileManager::~ConfigFileManager()
354    {
355        for(std::map<ConfigFileType, ConfigFile*>::const_iterator it = this->configFiles_.begin(); it != this->configFiles_.end(); )
356            delete (*(it++)).second;
357    }
358
359    ConfigFileManager* ConfigFileManager::getSingleton()
360    {
361        static ConfigFileManager instance;
362        return (&instance);
363    }
364
365    void ConfigFileManager::setFile(ConfigFileType type, const std::string& filename)
366    {
367        std::map<ConfigFileType, ConfigFile*>::const_iterator it = this->configFiles_.find(type);
368        if (it != this->configFiles_.end())
369            if ((*it).second != 0)
370                delete (*it).second;
371
372        this->configFiles_[type] = new ConfigFile(this->getFilePath(filename));
373        this->load(type);
374    }
375
376    void ConfigFileManager::load()
377    {
378        for(std::map<ConfigFileType, ConfigFile*>::const_iterator it = this->configFiles_.begin(); it != this->configFiles_.end(); ++it)
379            (*it).second->load();
380
381        this->updateConfigValues();
382    }
383
384    void ConfigFileManager::save()
385    {
386        for(std::map<ConfigFileType, ConfigFile*>::const_iterator it = this->configFiles_.begin(); it != this->configFiles_.end(); ++it)
387            (*it).second->save();
388    }
389
390    void ConfigFileManager::clean()
391    {
392        for(std::map<ConfigFileType, ConfigFile*>::const_iterator it = this->configFiles_.begin(); it != this->configFiles_.end(); ++it)
393            this->clean((*it).first);
394    }
395
396    void ConfigFileManager::load(ConfigFileType type)
397    {
398        this->getFile(type)->load();
399        this->updateConfigValues(type);
400    }
401
402    void ConfigFileManager::save(ConfigFileType type)
403    {
404        this->getFile(type)->save();
405    }
406
407    void ConfigFileManager::clean(ConfigFileType type)
408    {
409        this->getFile(type)->clean();
410        this->getFile(type)->save();
411    }
412
413    void ConfigFileManager::updateConfigValues() const
414    {
415        for(std::map<ConfigFileType, ConfigFile*>::const_iterator it = this->configFiles_.begin(); it != this->configFiles_.end(); ++it)
416            this->updateConfigValues((*it).first);
417    }
418
419    void ConfigFileManager::updateConfigValues(ConfigFileType type) const
420    {
421        if (type == CFT_Settings)
422        {
423            for (std::map<std::string, Identifier*>::const_iterator it = Identifier::getIdentifierMapBegin(); it != Identifier::getIdentifierMapEnd(); ++it)
424                if ((*it).second->hasConfigValues() /* && (*it).second != ClassManager<KeyBinder>::getIdentifier()*/)
425                    (*it).second->updateConfigValues();
426        }
427        else if (type == CFT_Keybindings)
428        {
429            // todo
430        }
431    }
432
433    ConfigFile* ConfigFileManager::getFile(ConfigFileType type)
434    {
435std::cout << "111111111111111111\n";
436        std::map<ConfigFileType, ConfigFile*>::iterator it = this->configFiles_.find(type);
437        if (it != this->configFiles_.end())
438            return (*it).second;
439
440        if (type == CFT_Settings)
441            return this->configFiles_[type] = new ConfigFile(DEFAULT_CONFIG_FILE);
442        else
443            return this->configFiles_[type] = new ConfigFile("");
444    }
445
446    std::string ConfigFileManager::getFilePath(const std::string& name) const
447    {
448        return name;
449    }
450}
Note: See TracBrowser for help on using the repository browser.