Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/libraries/core/ConfigFileManager.h @ 8844

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

merged doc branch back to trunk

  • Property svn:eol-style set to native
File size: 28.0 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    @ingroup Config ConfigFile
32    @brief Declaration of ConfigFileManager and its helper classes, used to load and save config files.
33*/
34
35#ifndef _ConfigFileManager_H__
36#define _ConfigFileManager_H__
37
38#include "CorePrereqs.h"
39
40#include <list>
41#include <map>
42#include <set>
43#include <string>
44#include <boost/array.hpp>
45
46#include "util/Singleton.h"
47
48namespace orxonox // tolua_export
49{ // tolua_export
50
51    /////////////////////
52    // ConfigFileEntry //
53    /////////////////////
54    /**
55        @brief This class represents an entry in the config file.
56
57        This class is pure virtual. Use one of the derived classes to define the type of the entry.
58    */
59    class _CoreExport ConfigFileEntry
60    {
61        public:
62            /// Destructor
63            virtual ~ConfigFileEntry() {};
64
65            /// Changes the value of the entry.
66            virtual void setValue(const std::string& value) = 0;
67            /// Returns the value of the entry.
68            virtual const std::string& getValue() const = 0;
69
70            /// Returns the name of the entry
71            virtual const std::string& getName() const = 0;
72
73            /// Changes the comment of the entry (will be placed after the value)
74            virtual void setComment(const std::string& comment) = 0;
75
76            /// Returns the index of the entry in a vector (used only if it is a vector)
77            virtual unsigned int getIndex() const { return 0; }
78
79            /// Defines if this entry is treated as string which means some special treatment of special characters.
80            virtual void setString(bool bString) = 0;
81
82            /// Returns the line as it will be stored in the config file.
83            virtual const std::string& getFileEntry() const = 0;
84    };
85
86
87    //////////////////////////
88    // ConfigFileEntryValue //
89    //////////////////////////
90    /**
91        @brief This class represents a normal value in the config file.
92    */
93    class _CoreExport ConfigFileEntryValue : public ConfigFileEntry
94    {
95        public:
96            /**
97                @brief Constructor: Initializes the entry.
98
99                @param name                 The name of the entry
100                @param value                The value of the entry
101                @param bString              If true, the value is treated as string which means some special treatment of special characters.
102                @param additionalComment    An optional comment that will be placed behind the value in the config file
103            */
104            inline ConfigFileEntryValue(const std::string& name, const std::string& value = "", bool bString = false, const std::string& additionalComment = "")
105                : name_(name)
106                , value_(value)
107                , additionalComment_(additionalComment)
108                , bString_(bString)
109                { this->update(); }
110
111            /// Destructor
112            inline virtual ~ConfigFileEntryValue() {}
113
114            inline virtual const std::string& getName() const
115                { return this->name_; }
116
117            inline virtual void setComment(const std::string& comment)
118                { this->additionalComment_ = comment; this->update(); }
119
120            inline virtual void setValue(const std::string& value)
121                { this->value_ = value; this->update(); }
122            inline virtual const std::string& getValue() const
123                { return this->value_; }
124
125            inline void virtual setString(bool bString)
126                { this->bString_ = bString; this->update(); }
127
128            inline virtual const std::string& getFileEntry() const
129                { return this->fileEntry_; }
130
131            /// Returns the "key" of the value (in this case it's just the name of the entry, but for vectors it's different)
132            inline virtual const std::string& getKeyString() const
133                { return this->name_; }
134
135        protected:
136            virtual void update();
137
138            const std::string name_;            ///< The name of the value
139            std::string value_;                 ///< The value
140            std::string additionalComment_;     ///< The additional comment
141            std::string fileEntry_;             ///< The string as it will be stored in the config file
142            bool bString_;                      ///< If true, the value is treated as string which means some special treatment of special characters.
143    };
144
145
146    ////////////////////////////////
147    // ConfigFileEntryVectorValue //
148    ////////////////////////////////
149    /**
150        @brief Subclass of ConfigFileEntryValue, represents an element of a vector.
151    */
152    class _CoreExport ConfigFileEntryVectorValue : public ConfigFileEntryValue
153    {
154        public:
155            /**
156                @brief Constructor: Initializes the entry.
157
158                @param name                 The name of the vector
159                @param index                The index of the element in the vector
160                @param value                The value of the element
161                @param bString              If true, the value is treated as string which means some special treatment of special characters.
162                @param additionalComment    An optional comment that will be placed behind the value in the config file
163            */
164            inline ConfigFileEntryVectorValue(const std::string& name, unsigned int index, const std::string& value = "", bool bString = false, const std::string& additionalComment = "")
165                : ConfigFileEntryValue(name, value, bString, additionalComment)
166                , index_(index)
167                { this->update(); /*No virtual calls in base class ctor*/ }
168
169            /// Destructor
170            inline ~ConfigFileEntryVectorValue() {}
171
172            inline unsigned int getIndex() const
173                { return this->index_; }
174
175            /// Returns the "key" of the value (the name of the vector plus the index of the element)
176            inline const std::string& getKeyString() const
177                { return this->keyString_; }
178
179        private:
180            void update();
181
182            unsigned int index_;        ///< The index of the element in the vector
183            std::string keyString_;     ///< The full name of the entry (the name of the vector plus the index of the element)
184    };
185
186
187    ////////////////////////////
188    // ConfigFileEntryComment //
189    ////////////////////////////
190    /**
191        @brief This class represents a line in the config file which contains only a comment.
192    */
193    class _CoreExport ConfigFileEntryComment : public ConfigFileEntry
194    {
195        public:
196            /// Constructor: Initializes the object.
197            inline ConfigFileEntryComment(const std::string& comment) : comment_(comment) {}
198
199            /// Destructor
200            inline virtual ~ConfigFileEntryComment() {}
201
202            inline virtual const std::string& getName() const
203                { return this->comment_; }
204
205            inline virtual void setComment(const std::string& comment)
206                { this->comment_ = comment; }
207
208            inline virtual void setValue(const std::string& value)
209                {}
210            inline virtual const std::string& getValue() const
211                { return BLANKSTRING; }
212
213            inline void setString(bool bString)
214                {}
215
216            inline virtual const std::string& getFileEntry() const
217                { return this->comment_; }
218
219        private:
220            std::string comment_;   ///< The comment
221    };
222
223
224    ///////////////////////
225    // ConfigFileSection //
226    ///////////////////////
227    /**
228        @brief Represents a section in a config file.
229
230        A section has a name and a list of config values.
231    */
232    class _CoreExport ConfigFileSection
233    {
234        friend class ConfigFile;
235        friend class SettingsConfigFile;
236
237        public:
238            /**
239                @brief Constructor: Initializes the section.
240
241                @param name The name of the section
242                @param additionalComment An additional comment placed after the title of the section in the config file
243            */
244            inline ConfigFileSection(const std::string& name, const std::string& additionalComment = "")
245                : name_(name)
246                , additionalComment_(additionalComment)
247                , bUpdated_(false)
248                {}
249            ~ConfigFileSection();
250
251            /// Returns the name of the section.
252            inline const std::string& getName() const
253                { return this->name_; }
254
255            /// Changes the comment which is placed after the title of the section in the config file.
256            inline void setComment(const std::string& comment)
257                { this->additionalComment_ = comment; }
258
259            /**
260                @brief Stores a value in the section. If the entry doesn't exist, it's created.
261
262                @param name     The name of the entry
263                @param value    The new value
264                @param bString  If true, the value is treated as string which means some special treatment of special characters.
265            */
266            inline void setValue(const std::string& name, const std::string& value, bool bString)
267                { this->getOrCreateEntry(name, value, bString)->setValue(value); }
268            /**
269                @brief Returns the value of a given entry in the section. Returns a blank string if the value doesn't exist.
270
271                @param name     The name of the entry
272                @param bString  If true, the value is treated as string which means some special treatment of special characters.
273            */
274            inline const std::string& getValue(const std::string& name, bool bString)
275            {
276                ConfigFileEntry* entry = this->getEntry(name);
277                if (entry)
278                {
279                    entry->setString(bString);  // if the entry was loaded from the config file, we have to tell it if it's a string
280                    return entry->getValue();
281                }
282                return BLANKSTRING;
283            }
284            /**
285                @brief Returns the value of a given entry in the section. If it doesn't exist, the entry is created using the fallback value.
286
287                @param name     The name of the entry
288                @param fallback The value that will be used if the entry doesn't exist
289                @param bString  If true, the value is treated as string which means some special treatment of special characters.
290            */
291            inline const std::string& getOrCreateValue(const std::string& name, const std::string& fallback, bool bString)
292                { return this->getOrCreateEntry(name, fallback, bString)->getValue(); }
293
294            /**
295                @brief Stores the value of an element of a vector in the section. If the entry doesn't exist, it's created.
296
297                @param name     The name of the vector
298                @param index    The index of the element in the vector
299                @param value    The new value
300                @param bString  If true, the value is treated as string which means some special treatment of special characters.
301            */
302            inline void setValue(const std::string& name, unsigned int index, const std::string& value, bool bString)
303                { this->getOrCreateEntry(name, index, value, bString)->setValue(value); }
304            /**
305                @brief Returns the value of a given element of a vector in the section. Returns a blank string if the value doesn't exist.
306
307                @param name     The name of the vector
308                @param index    The index of the element in the vector
309                @param bString  If true, the value is treated as string which means some special treatment of special characters.
310            */
311            inline const std::string& getValue(const std::string& name, unsigned int index, bool bString)
312            {
313                ConfigFileEntry* entry = this->getEntry(name, index);
314                if (entry)
315                {
316                    entry->setString(bString);  // if the entry was loaded from the config file, we have to tell it if it's a string
317                    return entry->getValue();
318                }
319                return BLANKSTRING;
320            }
321            /**
322                @brief Returns the value of a given element of a vector in the section. If it doesn't exist, the entry is created using the fallback value.
323
324                @param name     The name of the vector
325                @param index    The index of the element in the vector
326                @param fallback The value that will be used if the entry doesn't exist
327                @param bString  If true, the value is treated as string which means some special treatment of special characters.
328            */
329            inline const std::string& getOrCreateValue(const std::string& name, unsigned int index, const std::string& fallback, bool bString)
330                { return this->getOrCreateEntry(name, index, fallback, bString)->getValue(); }
331
332            void deleteVectorEntries(const std::string& name, unsigned int startindex = 0);
333            unsigned int getVectorSize(const std::string& name) const;
334
335            std::string getFileEntry() const;
336
337        private:
338            /// Returns the list of entries in this section.
339            std::list<ConfigFileEntry*>& getEntries()
340                { return this->entries_; }
341            /// Returns the begin-iterator of the list of entries in this section.
342            std::list<ConfigFileEntry*>::const_iterator getEntriesBegin() const
343                { return this->entries_.begin(); }
344            /// Returns the end-iterator of the list of entries in this section.
345            std::list<ConfigFileEntry*>::const_iterator getEntriesEnd() const
346                { return this->entries_.end(); }
347
348            std::list<ConfigFileEntry*>::iterator getOrCreateEntryIterator(const std::string& name, const std::string& fallback, bool bString);
349            std::list<ConfigFileEntry*>::iterator getOrCreateEntryIterator(const std::string& name, unsigned int index, const std::string& fallback, bool bString);
350
351            ConfigFileEntry* getEntry(const std::string& name) const;
352            /**
353                @brief Returns the entry with given name. If it doesn't exist, the entry is created using the fallback value.
354
355                @param name     The name of the entry
356                @param fallback The value that will be used if the entry doesn't exist
357                @param bString  If true, the value is treated as string which means some special treatment of special characters.
358            */
359            inline ConfigFileEntry* getOrCreateEntry(const std::string& name, const std::string& fallback, bool bString)
360                { return (*this->getOrCreateEntryIterator(name, fallback, bString)); }
361
362            ConfigFileEntry* getEntry(const std::string& name, unsigned int index) const;
363            /**
364                @brief Returns the entry that contains an element of a vector with given name. If it doesn't exist, the entry is created using the fallback value.
365
366                @param name     The name of the entry
367                @param index    The index of the element in the vector
368                @param fallback The value that will be used if the entry doesn't exist
369                @param bString  If true, the value is treated as string which means some special treatment of special characters.
370            */
371            inline ConfigFileEntry* getOrCreateEntry(const std::string& name, unsigned int index, const std::string& fallback, bool bString)
372                { return (*this->getOrCreateEntryIterator(name, index, fallback, bString)); }
373
374            std::string name_;                      ///< The name of the section
375            std::string additionalComment_;         ///< The additional comment which is placed after the title of the section in the config file
376            std::list<ConfigFileEntry*> entries_;   ///< The list of entries in this section
377            bool bUpdated_;                         ///< True if an entry is created
378    };
379
380
381    ////////////////
382    // ConfigFile //
383    ////////////////
384    /**
385        @brief This class represents a config file, which is stored on the hard-disk and contains config values in different sections.
386
387        It provides an interface to manipulate the sections and values.
388    */
389    class _CoreExport ConfigFile
390    {
391        public:
392            ConfigFile(const std::string& filename, bool bCopyFallbackFile = true);
393            virtual ~ConfigFile();
394
395            virtual void load();
396            virtual void save() const;
397            virtual void saveAs(const std::string& filename) const;
398            virtual void clear();
399
400            /// Returns the file-name of this config file
401            inline const std::string& getFilename()
402                { return this->filename_; }
403
404            /**
405                @brief Stores a value in the config file. If the entry or its section doesn't exist, it's created.
406
407                @param section  The name of the section
408                @param name     The name of the entry
409                @param value    The new value
410                @param bString  If true, the value is treated as string which means some special treatment of special characters.
411            */
412            inline void setValue(const std::string& section, const std::string& name, const std::string& value, bool bString)
413            {
414                this->getOrCreateSection(section)->setValue(name, value, bString);
415                this->save();
416            }
417            /**
418                @brief Returns the value of a given entry in the config file. Returns a blank string if the value doesn't exist.
419
420                @param section  The name of the section
421                @param name     The name of the entry
422                @param bString  If true, the value is treated as string which means some special treatment of special characters.
423            */
424            inline const std::string& getValue(const std::string& section, const std::string& name, bool bString)
425            {
426                ConfigFileSection* sectionPtr = this->getSection(section);
427                return (sectionPtr ? sectionPtr->getValue(name, bString) : BLANKSTRING);
428            }
429            /**
430                @brief Returns the value of a given entry in the config file. If it doesn't exist, the entry is created using the fallback value.
431
432                @param section  The name of the section
433                @param name     The name of the entry
434                @param fallback The value that will be used if the entry doesn't exist
435                @param bString  If true, the value is treated as string which means some special treatment of special characters.
436            */
437            inline const std::string& getOrCreateValue(const std::string& section, const std::string& name, const std::string& fallback, bool bString)
438            {
439                const std::string& output = this->getOrCreateSection(section)->getOrCreateValue(name, fallback, bString);
440                this->saveIfUpdated();
441                return output;
442            }
443
444            /**
445                @brief Stores the value of an element of a vector in the config file. If the entry or its section doesn't exist, it's created.
446
447                @param section  The name of the section
448                @param name     The name of the vector
449                @param index    The index of the element in the vector
450                @param value    The new value
451                @param bString  If true, the value is treated as string which means some special treatment of special characters.
452            */
453            inline void setValue(const std::string& section, const std::string& name, unsigned int index, const std::string& value, bool bString)
454            {
455                this->getOrCreateSection(section)->setValue(name, index, value, bString);
456                this->save();
457            }
458            /**
459                @brief Returns the value of a given element of a vector in the config file. Returns a blank string if the value doesn't exist.
460
461                @param section  The name of the section
462                @param name     The name of the vector
463                @param index    The index of the element in the vector
464                @param bString  If true, the value is treated as string which means some special treatment of special characters.
465            */
466            inline const std::string& getValue(const std::string& section, const std::string& name, unsigned int index, bool bString)
467            {
468                ConfigFileSection* sectionPtr = this->getSection(section);
469                return (sectionPtr ? sectionPtr->getValue(name, index, bString) : BLANKSTRING);
470            }
471            /**
472                @brief Returns the value of a given element of a vector in the config file. If it doesn't exist, the entry is created using the fallback value.
473
474                @param section  The name of the section
475                @param name     The name of the vector
476                @param index    The index of the element in the vector
477                @param fallback The value that will be used if the entry doesn't exist
478                @param bString  If true, the value is treated as string which means some special treatment of special characters.
479            */
480            const std::string& getOrCreateValue(const std::string& section, const std::string& name, unsigned int index, const std::string& fallback, bool bString)
481            {
482                const std::string& output = this->getOrCreateSection(section)->getOrCreateValue(name, index, fallback, bString);
483                this->saveIfUpdated();
484                return output;
485            }
486
487            void deleteVectorEntries(const std::string& section, const std::string& name, unsigned int startindex = 0);
488            /**
489                @brief Returns the size of a config vector.
490                @param section  The section of the vector
491                @param name     The name of the vector
492            */
493            inline unsigned int getVectorSize(const std::string& section, const std::string& name) const
494            {
495                ConfigFileSection* sectionPtr = this->getSection(section);
496                return (sectionPtr ? sectionPtr->getVectorSize(name) : 0);
497            }
498
499            static const char* DEFAULT_CONFIG_FOLDER;   ///< The folder where the default config files will be stored
500
501        protected:
502            ConfigFileSection* getSection(const std::string& section) const;
503            ConfigFileSection* getOrCreateSection(const std::string& section);
504
505            std::list<ConfigFileSection*> sections_;    ///< A list of sections in this config file
506
507        private:
508            void saveIfUpdated();
509
510            const std::string filename_;                ///< The filename of this config file
511            const bool bCopyFallbackFile_;              ///< If true, the default config file is copied into the config-directory before loading the file
512            bool bUpdated_;                             ///< Becomes true if a section is added
513    };
514
515
516    ////////////////////////
517    // SettingsConfigFile //
518    ////////////////////////
519    /**
520        @brief Child class of ConfigFile, used to store the settings of the game.
521
522        In addition to ConfigFile, this class provides an interface to manipulate the settings
523        with console commands and to cache entries in instances of ConfigValueContainer.
524
525        SettingsConfigFile is a Singleton, meaning there's only one instance of this class
526        (and thus only one config file that stores settings).
527    */
528    class _CoreExport SettingsConfigFile // tolua_export
529        : public ConfigFile, public Singleton<SettingsConfigFile>
530    { // tolua_export
531        friend class Singleton<SettingsConfigFile>;
532
533        public:
534            typedef std::multimap<std::string, std::pair<std::string, ConfigValueContainer*> > ContainerMap;
535
536            SettingsConfigFile(const std::string& filename);
537            ~SettingsConfigFile();
538
539            void load(); // tolua_export
540            void setFilename(const std::string& filename); // tolua_export
541            void clean(bool bCleanComments = false); // tolua_export
542
543            void config(const std::string& section, const std::string& entry, const std::string& value); // tolua_export
544            void tconfig(const std::string& section, const std::string& entry, const std::string& value); // tolua_export
545            std::string getConfig(const std::string& section, const std::string& entry); // tolua_export
546
547            void addConfigValueContainer(ConfigValueContainer* container);
548            void removeConfigValueContainer(ConfigValueContainer* container);
549
550            /// Returns a set containing the names of all sections in this config file.
551            inline const std::set<std::string>& getSectionNames()
552                { return this->sectionNames_; }
553            /// Returns the lower-bound-iterator of the @ref ConfigValueContainer "config value containers" for the given section.
554            inline ContainerMap::const_iterator getContainerLowerBound(const std::string section)
555                { return this->containers_.lower_bound(section); }
556            /// Returns the upper-bound-iterator of the @ref ConfigValueContainer "config value containers" for the given section.
557            inline ContainerMap::const_iterator getContainerUpperBound(const std::string section)
558                { return this->containers_.upper_bound(section); }
559
560            static SettingsConfigFile& getInstance() { return Singleton<SettingsConfigFile>::getInstance(); } // tolua_export
561
562        private:
563            void updateConfigValues();
564            bool configImpl(const std::string& section, const std::string& entry, const std::string& value, bool (ConfigValueContainer::*function)(const MultiType&));
565
566            ContainerMap containers_;                   ///< Stores all @ref ConfigValueContainer "config value containers"
567            std::set<std::string> sectionNames_;        ///< Stores all section names
568            static SettingsConfigFile* singletonPtr_s;  ///< The singleton pointer
569    }; // tolua_export
570
571
572    ///////////////////////
573    // ConfigFileManager //
574    ///////////////////////
575    /**
576        @brief Manages the different config files (settings, calibration, etc). Implemented as Singleton.
577    */
578    class _CoreExport ConfigFileManager : public Singleton<ConfigFileManager>
579    {
580        friend class Singleton<ConfigFileManager>;
581        public:
582            ConfigFileManager();
583            ~ConfigFileManager();
584
585            void setFilename(ConfigFileType::Value type, const std::string& filename);
586
587            /// Returns the config file of a given type (settings, calibration, etc.)
588            inline ConfigFile* getConfigFile(ConfigFileType::Value type)
589            {
590                // Check array bounds
591                return configFiles_.at(type);
592            }
593
594        private:
595            ConfigFileManager(const ConfigFileManager&);    ///< Copy-constructor: not implemented
596
597            boost::array<ConfigFile*, 3> configFiles_;      ///< Stores the config files for each type in an array (must have the same size like ConfigFileType::Value)
598            static ConfigFileManager* singletonPtr_s;       ///< Stores the singleton-pointer
599    };
600} // tolua_export
601
602#endif /* _ConfigFileManager_H__ */
Note: See TracBrowser for help on using the repository browser.