Index: /code/branches/core2/src/orxonox/core/CMakeLists.txt
===================================================================
--- /code/branches/core2/src/orxonox/core/CMakeLists.txt	(revision 1005)
+++ /code/branches/core2/src/orxonox/core/CMakeLists.txt	(revision 1006)
@@ -6,4 +6,5 @@
   IdentifierDistributor.cc
   MetaObjectList.cc
+  ConfigFileManager.cc
   ConfigValueContainer.cc
   Error.cc
Index: /code/branches/core2/src/orxonox/core/ConfigFileManager.cc
===================================================================
--- /code/branches/core2/src/orxonox/core/ConfigFileManager.cc	(revision 1006)
+++ /code/branches/core2/src/orxonox/core/ConfigFileManager.cc	(revision 1006)
@@ -0,0 +1,413 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *
+ *
+ *   License notice:
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation; either version 2
+ *   of the License, or (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "ConfigFileManager.h"
+#include "ConsoleCommand.h"
+#include "Identifier.h"
+#include "util/Convert.h"
+#include "util/String.h"
+
+#define CONFIG_FILE_MAX_LINELENGHT 1024
+
+namespace orxonox
+{
+    ConsoleCommandShortcutExtern(reloadConfig, AccessLevel::None);
+    ConsoleCommandShortcutExtern(saveConfig, AccessLevel::None);
+    ConsoleCommandShortcutExtern(cleanConfig, AccessLevel::None);
+    ConsoleCommandShortcutExtern(loadSettings, AccessLevel::None);
+    ConsoleCommandShortcutExtern(loadKeybindings, AccessLevel::None);
+
+    void reloadConfig()
+    {
+        ConfigFileManager::getInstance()->load();
+    }
+
+    void saveConfig()
+    {
+        ConfigFileManager::getInstance()->save();
+    }
+
+    void cleanConfig()
+    {
+        ConfigFileManager::getInstance()->clean();
+    }
+
+    void loadSettings(const std::string& filename)
+    {
+        ConfigFileManager::getInstance()->setFile(CFT_Settings, filename);
+    }
+
+    void loadKeybindings(const std::string& filename)
+    {
+        ConfigFileManager::getInstance()->setFile(CFT_Keybindings, filename);
+    }
+
+
+    //////////////////////////
+    // ConfigFileEntryValue //
+    //////////////////////////
+    std::string ConfigFileEntryValue::getFileEntry() const
+    {
+        if (this->additionalComment_ == "" || this->additionalComment_.size() == 0)
+            return (this->name_ + "=" + this->value_);
+        else
+            return (this->name_ + "=" + this->value_ + " " + this->additionalComment_);
+    }
+
+
+    ///////////////////////////////
+    // ConfigFileEntryArrayValue //
+    ///////////////////////////////
+    std::string ConfigFileEntryArrayValue::getFileEntry() const
+    {
+        if (this->additionalComment_ == "" || this->additionalComment_.size() == 0)
+            return (this->name_ + "[" + getConvertedValue<unsigned int, std::string>(this->index_, 0) + "]" + "=" + this->value_);
+        else
+            return (this->name_ + "[" + getConvertedValue<unsigned int, std::string>(this->index_, 0) + "]=" + this->value_ + " " + this->additionalComment_);
+    }
+
+
+    ///////////////////////
+    // ConfigFileSection //
+    ///////////////////////
+    ConfigFileSection::~ConfigFileSection()
+    {
+        for (std::list<ConfigFileEntry*>::iterator it = this->entries_.begin(); it != this->entries_.end(); )
+            delete (*(it++));
+    }
+
+    std::string ConfigFileSection::getFileEntry() const
+    {
+        if (this->additionalComment_ == "" || this->additionalComment_.size() == 0)
+            return (this->name_);
+        else
+            return (this->name_ + " " + this->additionalComment_);
+    }
+
+    std::list<ConfigFileEntry*>::iterator ConfigFileSection::getEntryIterator(const std::string& name, unsigned int index)
+    {
+        for (std::list<ConfigFileEntry*>::iterator it = this->entries_.begin(); it != this->entries_.end(); ++it)
+            if (((*it)->getName() == name) && ((*it)->getIndex() == index))
+                return it;
+
+        this->bUpdated_ = true;
+
+        if (index == 0)
+            return this->entries_.insert(this->entries_.end(), (ConfigFileEntry*)(new ConfigFileEntryArrayValue(name, index)));
+        else
+            return this->entries_.insert(this->getEntryIterator(name, index - 1), (ConfigFileEntry*)(new ConfigFileEntryArrayValue(name, index)));
+    }
+
+
+    ////////////////
+    // ConfigFile //
+    ////////////////
+    ConfigFile::~ConfigFile()
+    {
+        for (std::list<ConfigFileSection*>::iterator it = this->sections_.begin(); it != this->sections_.end(); )
+            delete (*(it++));
+    }
+
+    void ConfigFile::load()
+    {
+        // This creates the file if it's not existing
+        std::ofstream createFile;
+        createFile.open(this->filename_.c_str(), std::fstream::app);
+        createFile.close();
+
+        // Open the file
+        std::ifstream file;
+        file.open(this->filename_.c_str(), std::fstream::in);
+
+        if (!file.is_open())
+        {
+            COUT(1) << "An error occurred in ConfigFileManager.cc:" << std::endl;
+            COUT(1) << "Error: Couldn't open config-file \"" << this->filename_ << "\"." << std::endl;
+            return;
+        }
+
+        char linearray[CONFIG_FILE_MAX_LINELENGHT];
+
+        ConfigFileSection* newsection = 0;
+
+        while (file.good() && !file.eof())
+        {
+            file.getline(linearray, CONFIG_FILE_MAX_LINELENGHT);
+
+            std::string line = std::string(linearray);
+
+            std::string temp = getStripped(line);
+            if (!isEmpty(temp) && !isComment(temp))
+            {
+                unsigned int pos1 = line.find('[');
+                unsigned int pos2 = line.find(']');
+
+                if (pos1 != std::string::npos && pos2 != std::string::npos && pos2 > pos1 + 1)
+                {
+                    // New section
+                    std::string comment = temp.substr(pos2 + 1);
+                    if (isComment(comment))
+                        newsection = new ConfigFileSection(line.substr(pos1, pos2 - pos1 + 1), comment);
+                    else
+                        newsection = new ConfigFileSection(line.substr(pos1, pos2 - pos1 + 1));
+                    this->sections_.insert(this->sections_.end(), newsection);
+                    continue;
+                }
+            }
+
+            if (newsection != 0)
+            {
+                if (isComment(line))
+                {
+                    // New comment
+                    newsection->getEntries().insert(newsection->getEntries().end(), new ConfigFileEntryComment(line));
+                    continue;
+                }
+                else
+                {
+                    unsigned int pos1 = line.find('=');
+
+                    if (pos1 != std::string::npos && pos1 > 0)
+                    {
+                        // New entry
+
+                        unsigned int pos2 = line.find('[');
+                        unsigned int pos3 = line.find(']');
+
+                        std::string value = removeTrailingWhitespaces(line.substr(pos1 + 1));
+                        std::string comment = "";
+
+                        std::string betweenQuotes = getStringBetweenQuotes(value);
+                        if (value.size() > 0 && value[0] == '"' && betweenQuotes != "" && betweenQuotes.size() > 0)
+                        {
+                            value = betweenQuotes;
+                            comment = getComment(value.substr(betweenQuotes.size() + 2));
+                        }
+                        else
+                        {
+                            unsigned int pos4 = getCommentPosition(line);
+                            value = removeTrailingWhitespaces(line.substr(pos1 + 1, pos4 - pos1 - 1));
+                            comment = line.substr(pos4);
+                        }
+
+
+                        if (pos2 != std::string::npos && pos3 != std::string::npos && pos3 > pos2 + 1)
+                        {
+                            // There might be an array index
+                            unsigned int index = 0;
+                            if (ConvertValue(&index, line.substr(pos2 + 1, pos3 - pos2 - 1)))
+                            {
+                                // New array
+                                newsection->getEntries().insert(newsection->getEntries().end(), new ConfigFileEntryArrayValue(getStripped(line.substr(0, pos2)), index, value, comment));
+                                continue;
+                            }
+                        }
+
+                        // New value
+                        newsection->getEntries().insert(newsection->getEntries().end(), new ConfigFileEntryValue(getStripped(line.substr(0, pos1)), value, comment));
+                        continue;
+                    }
+                }
+            }
+        }
+
+        file.close();
+
+        // Save the file in case something changed (like stripped whitespaces)
+        this->save();
+    }
+
+    void ConfigFile::save() const
+    {
+        std::ofstream file;
+        file.open(this->filename_.c_str(), std::fstream::out);
+        file.setf(std::ios::fixed, std::ios::floatfield);
+        file.precision(6);
+
+        if (!file.is_open())
+        {
+            COUT(1) << "An error occurred in ConfigFileManager.cc:" << std::endl;
+            COUT(1) << "Error: Couldn't open config-file \"" << this->filename_ << "\"." << std::endl;
+            return;
+        }
+
+        for (std::list<ConfigFileSection*>::const_iterator it = this->sections_.begin(); it != this->sections_.end(); ++it)
+        {
+            file << (*it)->getFileEntry() << std::endl;
+
+            for (std::list<ConfigFileEntry*>::const_iterator it_entries = (*it)->getEntriesBegin(); it_entries != (*it)->getEntriesEnd(); ++it_entries)
+            {
+                file << (*it_entries)->getFileEntry() << std::endl;
+            }
+
+            file << std::endl;
+        }
+
+        file.close();
+    }
+
+    void ConfigFile::clean()
+    {
+    }
+
+    ConfigFileSection* ConfigFile::getSection(const std::string& section)
+    {
+        for (std::list<ConfigFileSection*>::iterator it = this->sections_.begin(); it != this->sections_.end(); ++it)
+            if ((*it)->getName() == section)
+                return (*it);
+
+        this->bUpdated_ = true;
+
+        return (*this->sections_.insert(this->sections_.begin(), new ConfigFileSection(section)));
+    }
+
+    void ConfigFile::saveIfUpdated()
+    {
+        bool sectionsUpdated = false;
+
+        for (std::list<ConfigFileSection*>::iterator it = this->sections_.begin(); it != this->sections_.end(); ++it)
+        {
+            if ((*it)->bUpdated_)
+            {
+                sectionsUpdated = true;
+                (*it)->bUpdated_ = false;
+            }
+        }
+
+        if (this->bUpdated_ || sectionsUpdated)
+        {
+            this->bUpdated_ = false;
+            this->save();
+        }
+    }
+
+
+    ///////////////////////
+    // ConfigFileManager //
+    ///////////////////////
+    ConfigFileManager::ConfigFileManager()
+    {
+        this->setFile(CFT_Settings, DEFAULT_CONFIG_FILE);
+    }
+
+    ConfigFileManager::~ConfigFileManager()
+    {
+        for(std::map<ConfigFileType, ConfigFile*>::const_iterator it = this->configFiles_.begin(); it != this->configFiles_.end(); )
+            delete (*(it++)).second;
+    }
+
+    ConfigFileManager* ConfigFileManager::getInstance()
+    {
+        static ConfigFileManager instance;
+        return (&instance);
+    }
+
+    void ConfigFileManager::setFile(ConfigFileType type, const std::string& filename)
+    {
+        std::map<ConfigFileType, ConfigFile*>::const_iterator it = this->configFiles_.find(type);
+        if (it != this->configFiles_.end())
+            if ((*it).second != 0)
+                delete (*it).second;
+
+        this->configFiles_[type] = new ConfigFile(this->getFilePath(filename));
+        this->load(type);
+    }
+
+    void ConfigFileManager::load()
+    {
+        for(std::map<ConfigFileType, ConfigFile*>::const_iterator it = this->configFiles_.begin(); it != this->configFiles_.end(); ++it)
+            (*it).second->load();
+
+        this->updateConfigValues();
+    }
+
+    void ConfigFileManager::save()
+    {
+        for(std::map<ConfigFileType, ConfigFile*>::const_iterator it = this->configFiles_.begin(); it != this->configFiles_.end(); ++it)
+            (*it).second->save();
+    }
+
+    void ConfigFileManager::clean()
+    {
+        for(std::map<ConfigFileType, ConfigFile*>::const_iterator it = this->configFiles_.begin(); it != this->configFiles_.end(); ++it)
+            this->clean((*it).first);
+    }
+
+    void ConfigFileManager::load(ConfigFileType type)
+    {
+        this->getFile(type)->load();
+        this->updateConfigValues(type);
+    }
+
+    void ConfigFileManager::save(ConfigFileType type)
+    {
+        this->getFile(type)->save();
+    }
+
+    void ConfigFileManager::clean(ConfigFileType type)
+    {
+        this->getFile(type)->clean();
+        this->getFile(type)->save();
+    }
+
+    void ConfigFileManager::updateConfigValues() const
+    {
+        for(std::map<ConfigFileType, ConfigFile*>::const_iterator it = this->configFiles_.begin(); it != this->configFiles_.end(); ++it)
+            this->updateConfigValues((*it).first);
+    }
+
+    void ConfigFileManager::updateConfigValues(ConfigFileType type) const
+    {
+        if (type == CFT_Settings)
+        {
+            for (std::map<std::string, Identifier*>::const_iterator it = Identifier::getIdentifierMapBegin(); it != Identifier::getIdentifierMapEnd(); ++it)
+                if ((*it).second->hasConfigValues() /* && (*it).second != ClassManager<KeyBinder>::getIdentifier()*/)
+                    (*it).second->updateConfigValues();
+        }
+        else if (type == CFT_Keybindings)
+        {
+            // todo
+        }
+    }
+
+    ConfigFile* ConfigFileManager::getFile(ConfigFileType type)
+    {
+        std::map<ConfigFileType, ConfigFile*>::iterator it = this->configFiles_.find(type);
+        if (it != this->configFiles_.end())
+            return (*it).second;
+
+        if (type == CFT_Settings)
+            return this->configFiles_[type] = new ConfigFile(DEFAULT_CONFIG_FILE);
+        else
+            return this->configFiles_[type] = new ConfigFile("");
+    }
+
+    std::string ConfigFileManager::getFilePath(const std::string& name) const
+    {
+        return name;
+    }
+}
Index: /code/branches/core2/src/orxonox/core/ConfigFileManager.h
===================================================================
--- /code/branches/core2/src/orxonox/core/ConfigFileManager.h	(revision 1005)
+++ /code/branches/core2/src/orxonox/core/ConfigFileManager.h	(revision 1006)
@@ -29,79 +29,243 @@
 #define _ConfigFileManager_H__
 
+#include <iostream>
+#include <string>
 #include <list>
+#include <map>
+
+#include "util/Math.h"
 
 #include "CorePrereqs.h"
+
+#define DEFAULT_CONFIG_FILE "default.ini"
 
 namespace orxonox
 {
-    class ConfigFileEntry
-    {
-        public:
-            ConfigFileEntry(const std::string& name, const std::string& value = "");
-
-            void setValue(const std::string& value);
-            const std::string& getValue() const;
-            const std::string& getName() const;
-
-        private:
+    enum _CoreExport ConfigFileType
+    {
+        CFT_Settings,
+        CFT_Keybindings
+    };
+
+
+    void reloadConfig();
+    void saveConfig();
+    void cleanConfig();
+    void loadSettings(const std::string& filename);
+    void loadKeybindings(const std::string& filename);
+
+
+    /////////////////////
+    // ConfigFileEntry //
+    /////////////////////
+    class _CoreExport ConfigFileEntry
+    {
+        public:
+            virtual void setValue(const std::string& value) = 0;
+            virtual const std::string& getValue() const = 0;
+            virtual const std::string& getName() const = 0;
+            virtual unsigned int getIndex() const { return 0; }
+            virtual std::string getFileEntry() const = 0;
+    };
+
+
+    //////////////////////////
+    // ConfigFileEntryValue //
+    //////////////////////////
+    class _CoreExport ConfigFileEntryValue : public ConfigFileEntry
+    {
+        public:
+            inline ConfigFileEntryValue(const std::string& name, const std::string& value = "", const std::string& additionalComment = "") : name_(name), value_(value), additionalComment_(additionalComment), bString_(false) {}
+            inline virtual ~ConfigFileEntryValue() {}
+
+            inline virtual const std::string& getName() const
+                { return this->name_; }
+
+            inline virtual void setValue(const std::string& value)
+                { this->value_ = value; }
+            inline virtual const std::string& getValue() const
+                { return this->value_; }
+
+            inline bool isString() const
+                { return this->bString_; }
+            inline void setString(bool bString)
+                { this->bString_ = bString; }
+
+            virtual std::string getFileEntry() const;
+
+        protected:
             std::string name_;
             std::string value_;
-    };
-
-    class ConfigFileSection
-    {
-        public:
-            void addEntry(const std::string& name);
-            ConfigFileEntry* getEntry(const std::string& name) const;
-
-            void setValue(const std::string& name, const std::string& value);
-            const std::string& getValue(const std::string& name) const;
-
-        private:
+            std::string additionalComment_;
+            bool bString_;
+    };
+
+
+    ///////////////////////////////
+    // ConfigFileEntryArrayValue //
+    ///////////////////////////////
+    class _CoreExport ConfigFileEntryArrayValue : public ConfigFileEntryValue
+    {
+        public:
+            inline ConfigFileEntryArrayValue(const std::string& name, unsigned int index, const std::string& value = "", const std::string& additionalComment = "") : ConfigFileEntryValue(name, value, additionalComment), index_(index) {}
+            inline virtual ~ConfigFileEntryArrayValue() {}
+
+            inline virtual unsigned int getIndex() const
+                { return this->index_; }
+
+            virtual std::string getFileEntry() const;
+
+        private:
+            unsigned int index_;
+    };
+
+
+    ////////////////////////////
+    // ConfigFileEntryComment //
+    ////////////////////////////
+    class _CoreExport ConfigFileEntryComment : public ConfigFileEntry
+    {
+        public:
+            inline ConfigFileEntryComment(const std::string& comment) : comment_(comment) {}
+            inline virtual ~ConfigFileEntryComment() {}
+
+            inline virtual const std::string& getName() const
+                { return this->comment_; }
+
+            inline virtual void setValue(const std::string& value)
+                {}
+            inline virtual const std::string& getValue() const
+                { return this->comment_; }
+
+            inline virtual std::string getFileEntry() const
+                { return this->comment_; }
+
+        private:
+            std::string comment_;
+    };
+
+
+    ///////////////////////
+    // ConfigFileSection //
+    ///////////////////////
+    class _CoreExport ConfigFileSection
+    {
+        friend class ConfigFile;
+
+        public:
+            inline ConfigFileSection(const std::string& name, const std::string& additionalComment = "") : name_(name), additionalComment_(additionalComment), bUpdated_(false) {}
+            ~ConfigFileSection();
+
+            inline const std::string& getName() const
+                { return this->name_; }
+
+            inline void setValue(const std::string& name, const std::string& value)
+                { this->getEntry(name)->setValue(value); }
+            inline const std::string& getValue(const std::string& name)
+                { return this->getEntry(name)->getValue(); }
+
+            inline void setValue(const std::string& name, unsigned int index, const std::string& value)
+                { this->getEntry(name, index)->setValue(value); }
+            inline const std::string& getValue(const std::string& name, unsigned int index)
+                { return this->getEntry(name, index)->getValue(); }
+
+            std::string getFileEntry() const;
+
+        private:
+            std::list<ConfigFileEntry*>& getEntries()
+                { return this->entries_; }
+            std::list<ConfigFileEntry*>::const_iterator getEntriesBegin() const
+                { return this->entries_.begin(); }
+            std::list<ConfigFileEntry*>::const_iterator getEntriesEnd() const
+                { return this->entries_.end(); }
+
+            std::list<ConfigFileEntry*>::iterator getEntryIterator(const std::string& name, unsigned int index);
+
+            inline ConfigFileEntry* getEntry(const std::string& name)
+                { return (*this->getEntryIterator(name, 0)); }
+            inline ConfigFileEntry* getEntry(const std::string& name, unsigned int index)
+                { return (*this->getEntryIterator(name, index)); }
+
             std::string name_;
-            std::list<ConfigFileEntry> entries_;
-    };
-
-    class ConfigFile
-    {
-        public:
-            enum Type
-            {
-                Settings,
-                Keybindings
-            };
-
-        public:
+            std::string additionalComment_;
+            std::list<ConfigFileEntry*> entries_;
+            bool bUpdated_;
+    };
+
+
+    ////////////////
+    // ConfigFile //
+    ////////////////
+    class _CoreExport ConfigFile
+    {
+        public:
+            inline ConfigFile(const std::string& filename) : filename_(filename), bUpdated_(false) {}
+            ~ConfigFile();
+
+            void load();
+            void save() const;
+            void clean();
+
+            inline void setValue(const std::string& section, const std::string& name, const std::string& value)
+                { this->getSection(section)->setValue(name, value); this->save(); }
+            inline const std::string& getValue(const std::string& section, const std::string& name)
+                { return this->getSection(section)->getValue(name); this->saveIfUpdated(); }
+
+            inline void setValue(const std::string& section, const std::string& name, unsigned int index, const std::string& value)
+                { this->getSection(section)->setValue(name, index, value); this->save(); }
+            inline const std::string& getValue(const std::string& section, const std::string& name, unsigned int index)
+                { return this->getSection(section)->getValue(name, index); this->saveIfUpdated(); }
+
+        private:
+            ConfigFileSection* getSection(const std::string& section);
+            void saveIfUpdated();
+
+            std::string filename_;
+            std::list<ConfigFileSection*> sections_;
+            bool bUpdated_;
+    };
+
+
+    ///////////////////////
+    // ConfigFileManager //
+    ///////////////////////
+    class _CoreExport ConfigFileManager
+    {
+        public:
+            static ConfigFileManager* getInstance();
+
+            void setFile(ConfigFileType type, const std::string& filename);
+
             void load();
             void save();
-
-            void addSection(const std::string& name);
-            ConfigFileSection* getSection(const std::string& name) const;
-
-            void setValue(const std::string& section, const std::string& name, const std::string& value);
-            const std::string& getValue(const std::string& section, const std::string& name) const;
-
-        private:
-            std::string name_;
-            Type type_;
-            std::list<ConfigFileSection> sections_;
-    };
-
-    class ConfigFileManager
-    {
-        public:
-            static ConfigFileManater* getInstance();
-
-            void load(const std::string& filename);
-            void save(const std::string& filename) const;
-
-            void setFile(const std::string& filename);
-            ConfigFile& getFile(const std::string& filename) const;
-
-            void setValue(const std::string& filename, const std::string& section, const std::string& name, const std::string& value);
-            const std::string& getValue(const std::string& filename, const std::string& section, const std::string& name) const;
-
-        private:
-            std::list<ConfigFile> configFiles_;
+            void clean();
+
+            void load(ConfigFileType type);
+            void save(ConfigFileType type);
+            void clean(ConfigFileType type);
+
+            inline void setValue(ConfigFileType type, const std::string& section, const std::string& name, const std::string& value)
+                { this->getFile(type)->setValue(section, name, value); }
+            inline const std::string& getValue(ConfigFileType type, const std::string& section, const std::string& name)
+                { return this->getFile(type)->getValue(section, name); }
+
+            inline void setValue(ConfigFileType type, const std::string& section, const std::string& name, unsigned int index, const std::string& value)
+                { this->getFile(type)->setValue(section, name, index, value); }
+            inline const std::string& getValue(ConfigFileType type, const std::string& section, const std::string& name, unsigned int index)
+                { return this->getFile(type)->getValue(section, name, index); }
+
+            void updateConfigValues() const;
+            void updateConfigValues(ConfigFileType type) const;
+
+        private:
+            ConfigFileManager();
+            ConfigFileManager(const ConfigFileManager& other) {}
+            ~ConfigFileManager();
+
+            ConfigFile* getFile(ConfigFileType type);
+
+            std::string getFilePath(const std::string& name) const;
+
+            std::map<ConfigFileType, ConfigFile*> configFiles_;
     };
 }
Index: /code/branches/core2/src/util/String.cc
===================================================================
--- /code/branches/core2/src/util/String.cc	(revision 1005)
+++ /code/branches/core2/src/util/String.cc	(revision 1006)
@@ -53,4 +53,31 @@
     strip(&output);
     return output;
+}
+
+/**
+    @brief Returns a copy of a string without trailing whitespaces.
+    @param str The string
+    @return The modified copy
+*/
+std::string removeTrailingWhitespaces(const std::string& str)
+{
+}
+
+/**
+    @brief Returns true if the string contains something like '..."between quotes"...'
+    @param The string
+    @return True if there is something between quotes
+*/
+bool hasStringBetweenQuotes(const std::string& str)
+{
+}
+
+/**
+    @brief If the string contains something like '..."between quotes"...' then 'between quotes' gets returned (without quotes).
+    @param The string
+    @param The string between the quotes
+*/
+std::string getStringBetweenQuotes(const std::string& str)
+{
 }
 
@@ -218,8 +245,8 @@
 
 /**
- * @brief compares two strings without ignoring the case
- * @param s1 first string
- * @param s2 second string
- */
+    @brief compares two strings without ignoring the case
+    @param s1 first string
+    @param s2 second string
+*/
 int nocaseCmp(const std::string& s1, const std::string& s2)
 {
@@ -246,9 +273,9 @@
 
 /**
- * @brief compares two strings without ignoring the case
- * @param s1 first string
- * @param s2 second string
- * @param len how far from the beginning to start.
- */
+    @brief compares two strings without ignoring the case
+    @param s1 first string
+    @param s2 second string
+    @param len how far from the beginning to start.
+*/
 int nocaseCmp(const std::string& s1, const std::string& s2, unsigned int len)
 {
@@ -270,2 +297,36 @@
     return 0;
 }
+
+/**
+    @brief Returns true if the string contains a comment, introduced by #, %, ; or //.
+    @param str The string
+    @return True if the string contains a comment
+*/
+bool hasComment(const std::string& str)
+{
+    return (getCommentPosition(str) != std::string::npos);
+}
+
+/**
+    @brief If the string contains a comment, the comment gets returned (including the comment symbol), an empty string otherwise.
+    @param str The string
+    @return The comment
+*/
+std::string getComment(const std::string& str)
+{
+    return str.substr(getCommentPosition(str));
+}
+
+/**
+    @brief If the string contains a comment, the position of the comment-symbol gets returned, std::string::npos otherwise.
+    @param str The string
+    @return The position
+*/
+unsigned int getCommentPosition(const std::string& str)
+{
+    for (unsigned int i = 0; i < str.size(); i++)
+        if (isComment(str.substr(i)))
+            return i;
+
+    return std::string::npos;
+}
Index: /code/branches/core2/src/util/String.h
===================================================================
--- /code/branches/core2/src/util/String.h	(revision 1005)
+++ /code/branches/core2/src/util/String.h	(revision 1006)
@@ -34,22 +34,31 @@
 #include "UtilPrereqs.h"
 
-_UtilExport void        strip(std::string* str);
-_UtilExport std::string getStripped(const std::string& str);
+_UtilExport void         strip(std::string* str);
+_UtilExport std::string  getStripped(const std::string& str);
 
-_UtilExport void        stripEnclosingQuotes(std::string* str);
-_UtilExport std::string getStrippedEnclosingQuotes(const std::string& str);
+_UtilExport std::string  removeTrailingWhitespaces(const std::string& str);
 
-_UtilExport bool        isEmpty(const std::string& str);
-_UtilExport bool        isComment(const std::string& str);
-_UtilExport bool        isNumeric(const std::string& str);
+_UtilExport bool         hasStringBetweenQuotes(const std::string& str);
+_UtilExport std::string  getStringBetweenQuotes(const std::string& str);
 
-_UtilExport void        lowercase(std::string* str);
-_UtilExport std::string getLowercase(const std::string& str);
+_UtilExport void         stripEnclosingQuotes(std::string* str);
+_UtilExport std::string  getStrippedEnclosingQuotes(const std::string& str);
 
-_UtilExport void        uppercase(std::string* str);
-_UtilExport std::string getUppercase(const std::string& str);
+_UtilExport bool         isEmpty(const std::string& str);
+_UtilExport bool         isComment(const std::string& str);
+_UtilExport bool         isNumeric(const std::string& str);
 
-_UtilExport int         nocaseCmp(const std::string& s1, const std::string& s2);
-_UtilExport int         nocaseCmp(const std::string& s1, const std::string& s2, unsigned int len);
+_UtilExport void         lowercase(std::string* str);
+_UtilExport std::string  getLowercase(const std::string& str);
+
+_UtilExport void         uppercase(std::string* str);
+_UtilExport std::string  getUppercase(const std::string& str);
+
+_UtilExport int          nocaseCmp(const std::string& s1, const std::string& s2);
+_UtilExport int          nocaseCmp(const std::string& s1, const std::string& s2, unsigned int len);
+
+_UtilExport bool         hasComment(const std::string& str);
+_UtilExport std::string  getComment(const std::string& str);
+_UtilExport unsigned int getCommentPosition(const std::string& str);
 
 //! The Convert class has some static member functions to convert strings to values and values to strings.
